diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8daf2f468..737d523ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: - master - tiddlywiki-com env: - NODE_VERSION: "12" + NODE_VERSION: "18" jobs: test: runs-on: ubuntu-latest @@ -14,7 +14,13 @@ jobs: - uses: actions/setup-node@v1 with: node-version: "${{ env.NODE_VERSION }}" - - run: "./bin/test.sh" + - run: "./bin/ci-test.sh" + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 build-prerelease: runs-on: ubuntu-latest if: github.ref == 'refs/heads/master' @@ -54,6 +60,7 @@ jobs: TW5_BUILD_TIDDLYWIKI: "./node_modules/tiddlywiki/tiddlywiki.js" TW5_BUILD_MAIN_EDITION: "./editions/tw5.com" TW5_BUILD_OUTPUT: "./output" + TW5_BUILD_ARCHIVE: "./output" steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 diff --git a/.gitignore b/.gitignore index ad7e8e07f..0ab5b300f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ .DS_Store .c9/ +.vs/ .vscode/ tmp/ output/ node_modules/ - +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/bin/build-site.sh b/bin/build-site.sh index 388782da4..a2193953d 100755 --- a/bin/build-site.sh +++ b/bin/build-site.sh @@ -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.2.3 + TW5_BUILD_VERSION=v5.3.3 fi echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]" @@ -84,10 +84,27 @@ echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" ###################################################### # -# Core distribution +# Core distributions # ###################################################### +# Conditionally build archive if $TW5_BUILD_ARCHIVE variable is set, otherwise do nothing +# +# /archive/Empty-TiddlyWiki-.html Empty archived version +# /archive/TiddlyWiki-.html Full archived version + +if [ -n "$TW5_BUILD_ARCHIVE" ]; then + +node $TW5_BUILD_TIDDLYWIKI \ + $TW5_BUILD_MAIN_EDITION \ + --verbose \ + --version \ + --load $TW5_BUILD_OUTPUT/build.tid \ + --output $TW5_BUILD_ARCHIVE \ + --build archive \ + || exit 1 +fi + # /index.html Main site # /favicon.ico Favicon for main site # /static.html Static rendering of default tiddlers @@ -95,6 +112,7 @@ echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" # /static/* Static single tiddlers # /static/static.css Static stylesheet # /static/favicon.ico Favicon for static pages + node $TW5_BUILD_TIDDLYWIKI \ $TW5_BUILD_MAIN_EDITION \ --verbose \ @@ -104,13 +122,15 @@ node $TW5_BUILD_TIDDLYWIKI \ --build favicon static index \ || exit 1 -# /empty.html Empty -# /empty.hta For Internet Explorer +# /empty.html Empty +# /empty.hta For Internet Explorer +# /empty-external-core.html External core empty +# /tiddlywikicore-.js Core plugin javascript node $TW5_BUILD_TIDDLYWIKI \ - $TW5_BUILD_MAIN_EDITION \ + ./editions/empty \ --verbose \ --output $TW5_BUILD_OUTPUT \ - --build empty \ + --build empty emptyexternalcore \ || exit 1 @@ -136,6 +156,28 @@ node $TW5_BUILD_TIDDLYWIKI \ --build index favicon static \ || exit 1 +# /tour.html tour edition +node $TW5_BUILD_TIDDLYWIKI \ + ./editions/tour \ + --verbose \ + --output $TW5_BUILD_OUTPUT \ + --rendertiddler $:/core/save/all tour.html text/plain \ + || exit 1 + +# /dev/index.html Developer docs +# /dev/favicon.ico Favicon for dev site +# /dev/static.html Static rendering of default tiddlers +# /dev/alltiddlers.html Static rendering of all tiddlers +# /dev/static/* Static single tiddlers +# /dev/static/static.css Static stylesheet +node $TW5_BUILD_TIDDLYWIKI \ + ./editions/dev \ + --verbose \ + --load $TW5_BUILD_OUTPUT/build.tid \ + --output $TW5_BUILD_OUTPUT/dev \ + --build index favicon static \ + || exit 1 + # /share.html Custom edition for sharing via the URL node $TW5_BUILD_TIDDLYWIKI \ ./editions/share \ @@ -359,14 +401,14 @@ node $TW5_BUILD_TIDDLYWIKI \ # Delete any existing static content -rm $TW5_BUILD_OUTPUT/languages/de-AT/static/* -rm $TW5_BUILD_OUTPUT/languages/de-DE/static/* -rm $TW5_BUILD_OUTPUT/languages/es-ES/static/* -rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/* -rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/* -rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/* -rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/* -rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/de-AT/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/de-DE/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/es-ES/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/fr-FR/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/ja-JP/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/ko-KR/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hans/static/* +rm -rf $TW5_BUILD_OUTPUT/languages/zh-Hant/static/* # /languages/de-AT/index.html Demo wiki with de-AT language # /languages/de-AT/empty.html Empty wiki with de-AT language diff --git a/bin/ci-test.sh b/bin/ci-test.sh new file mode 100755 index 000000000..ffcae66b2 --- /dev/null +++ b/bin/ci-test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# test TiddlyWiki5 for tiddlywiki.com + +node ./tiddlywiki.js \ + ./editions/test \ + --verbose \ + --version \ + --rendertiddler $:/core/save/all test.html text/plain \ + --test \ + || exit 1 + +npm install playwright @playwright/test +npx playwright install chromium firefox --with-deps + +npx playwright test diff --git a/bin/clean.sh b/bin/clean.sh index 522479edb..5a56e1971 100755 --- a/bin/clean.sh +++ b/bin/clean.sh @@ -2,4 +2,4 @@ # Remove any output files -find . -regex "^./editions/[a-z0-9\.-]*/output/.*" -delete +find . -regex "^./editions/.*/output/.*" -delete diff --git a/boot/boot.js b/boot/boot.js index c64b881f4..64cedab77 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -313,7 +313,7 @@ $tw.utils.getLocationHash = function() { var idx = href.indexOf('#'); if(idx === -1) { return "#"; - } else if(idx < href.length-1 && href[idx+1] === '#') { + } else if(href.substr(idx + 1,1) === "#" || href.substr(idx + 1,3) === "%23") { // Special case: ignore location hash if it itself starts with a # return "#"; } else { @@ -375,7 +375,7 @@ $tw.utils.stringifyList = function(value) { var result = new Array(value.length); for(var t=0, l=value.length; t \ No newline at end of file +\parameters (size:"22pt") +> height=<> viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/add-comment.tid b/core/images/add-comment.tid index 178221806..a118506ed 100644 --- a/core/images/add-comment.tid +++ b/core/images/add-comment.tid @@ -1,4 +1,5 @@ title: $:/core/images/add-comment tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-add-comment tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/advanced-search-button.tid b/core/images/advanced-search-button.tid index 6fda3fe8b..8e5699c4d 100755 --- a/core/images/advanced-search-button.tid +++ b/core/images/advanced-search-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/advanced-search-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-advanced-search-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/auto-height.tid b/core/images/auto-height.tid index 78f95418b..76deecbad 100755 --- a/core/images/auto-height.tid +++ b/core/images/auto-height.tid @@ -1,4 +1,5 @@ title: $:/core/images/auto-height tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-auto-height tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/blank.tid b/core/images/blank.tid index 731b55a5a..565ef6bec 100755 --- a/core/images/blank.tid +++ b/core/images/blank.tid @@ -1,4 +1,5 @@ title: $:/core/images/blank tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-blank tc-image-button" viewBox="0 0 128 128"/> \ No newline at end of file diff --git a/core/images/bold.tid b/core/images/bold.tid index 67a00f894..d9259e4a1 100755 --- a/core/images/bold.tid +++ b/core/images/bold.tid @@ -1,4 +1,5 @@ title: $:/core/images/bold tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-bold tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/cancel-button.tid b/core/images/cancel-button.tid index c55620b06..3bb982bc1 100755 --- a/core/images/cancel-button.tid +++ b/core/images/cancel-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/cancel-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-cancel-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/chevron-down.tid b/core/images/chevron-down.tid index f1b363dfc..df28c87a4 100755 --- a/core/images/chevron-down.tid +++ b/core/images/chevron-down.tid @@ -1,4 +1,5 @@ title: $:/core/images/chevron-down tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-chevron-down tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/chevron-left.tid b/core/images/chevron-left.tid index e4c69d95a..b7f9ad7ae 100755 --- a/core/images/chevron-left.tid +++ b/core/images/chevron-left.tid @@ -1,4 +1,5 @@ title: $:/core/images/chevron-left tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-chevron-left tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/chevron-right.tid b/core/images/chevron-right.tid index 6ff5b6c0d..9ec7c96fe 100755 --- a/core/images/chevron-right.tid +++ b/core/images/chevron-right.tid @@ -1,4 +1,5 @@ title: $:/core/images/chevron-right tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-chevron-right tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/chevron-up.tid b/core/images/chevron-up.tid index 9acbdec40..45366f286 100755 --- a/core/images/chevron-up.tid +++ b/core/images/chevron-up.tid @@ -1,4 +1,5 @@ title: $:/core/images/chevron-up tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-chevron-up tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/clone-button.tid b/core/images/clone-button.tid index 9ff4903ad..cc0ed7595 100755 --- a/core/images/clone-button.tid +++ b/core/images/clone-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/clone-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-clone-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/close-all-button.tid b/core/images/close-all-button.tid index 3334c5dbc..02d25fa6f 100755 --- a/core/images/close-all-button.tid +++ b/core/images/close-all-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/close-all-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-close-all-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/close-button.tid b/core/images/close-button.tid index c462c9bac..a05669ccd 100755 --- a/core/images/close-button.tid +++ b/core/images/close-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/close-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-close-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/close-others-button.tid b/core/images/close-others-button.tid index 1cd54d797..6eb779018 100755 --- a/core/images/close-others-button.tid +++ b/core/images/close-others-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/close-others-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-close-others-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/copy-clipboard.tid b/core/images/copy-clipboard.tid index e4e55b6e9..d6514ad7c 100644 --- a/core/images/copy-clipboard.tid +++ b/core/images/copy-clipboard.tid @@ -1,4 +1,5 @@ title: $:/core/images/copy-clipboard tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-copy-clipboard tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/delete-button.tid b/core/images/delete-button.tid index e8c9b6108..99f83b3ba 100755 --- a/core/images/delete-button.tid +++ b/core/images/delete-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/delete-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-delete-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/done-button.tid b/core/images/done-button.tid index 265528d06..7672b7d27 100755 --- a/core/images/done-button.tid +++ b/core/images/done-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/done-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-done-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/down-arrow.tid b/core/images/down-arrow.tid index 4cac65a00..7f1273b2c 100755 --- a/core/images/down-arrow.tid +++ b/core/images/down-arrow.tid @@ -1,4 +1,5 @@ title: $:/core/images/down-arrow tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-down-arrow tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/download-button.tid b/core/images/download-button.tid index e3a549639..8b06356ab 100755 --- a/core/images/download-button.tid +++ b/core/images/download-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/download-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-download-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/edit-button.tid b/core/images/edit-button.tid index 190dffc41..e4644ef7c 100755 --- a/core/images/edit-button.tid +++ b/core/images/edit-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/edit-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-edit-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/erase.tid b/core/images/erase.tid index 22b31e7cc..6cc2011a9 100755 --- a/core/images/erase.tid +++ b/core/images/erase.tid @@ -1,4 +1,5 @@ title: $:/core/images/erase tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-erase tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/excise.tid b/core/images/excise.tid index e6c2c9404..fa351baff 100755 --- a/core/images/excise.tid +++ b/core/images/excise.tid @@ -1,4 +1,5 @@ title: $:/core/images/excise tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-excise tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/export-button.tid b/core/images/export-button.tid index eb3284c80..b9f0dca7f 100755 --- a/core/images/export-button.tid +++ b/core/images/export-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/export-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-export-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/file.tid b/core/images/file.tid index 67ebc22ac..682796fbf 100755 --- a/core/images/file.tid +++ b/core/images/file.tid @@ -1,4 +1,5 @@ title: $:/core/images/file tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-file tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/fixed-height.tid b/core/images/fixed-height.tid index c15162267..b2b5083b9 100755 --- a/core/images/fixed-height.tid +++ b/core/images/fixed-height.tid @@ -1,4 +1,5 @@ title: $:/core/images/fixed-height tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-fixed-height tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/fold-all-button.tid b/core/images/fold-all-button.tid index edff8b22b..260efe9b8 100755 --- a/core/images/fold-all-button.tid +++ b/core/images/fold-all-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/fold-all-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-fold-all tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/fold-button.tid b/core/images/fold-button.tid index f0b2b474d..cfc2291a5 100755 --- a/core/images/fold-button.tid +++ b/core/images/fold-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/fold-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-fold tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/fold-others-button.tid b/core/images/fold-others-button.tid index 5cb086f85..a5457c461 100755 --- a/core/images/fold-others-button.tid +++ b/core/images/fold-others-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/fold-others-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-fold-others tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/folder.tid b/core/images/folder.tid index 4b89418ff..8c5d7efb1 100755 --- a/core/images/folder.tid +++ b/core/images/folder.tid @@ -1,4 +1,5 @@ title: $:/core/images/folder tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-folder tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/full-screen-button.tid b/core/images/full-screen-button.tid index 8572ff646..7e20183b7 100755 --- a/core/images/full-screen-button.tid +++ b/core/images/full-screen-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/full-screen-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-full-screen-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/github.tid b/core/images/github.tid index 6389f5cdc..b82c54e72 100755 --- a/core/images/github.tid +++ b/core/images/github.tid @@ -1,4 +1,5 @@ title: $:/core/images/github tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-github tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/gitter.tid b/core/images/gitter.tid index 876fc3da1..4af54ddba 100644 --- a/core/images/gitter.tid +++ b/core/images/gitter.tid @@ -1,4 +1,5 @@ title: $:/core/images/gitter tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-gitter tc-image-button" viewBox="0 0 18 25"> \ No newline at end of file diff --git a/core/images/globe.tid b/core/images/globe.tid index 9448ed7a4..0e2c56b40 100755 --- a/core/images/globe.tid +++ b/core/images/globe.tid @@ -1,4 +1,5 @@ title: $:/core/images/globe tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-globe tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-1.tid b/core/images/heading-1.tid index f8a98123b..d160284c9 100755 --- a/core/images/heading-1.tid +++ b/core/images/heading-1.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-1 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-1 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-2.tid b/core/images/heading-2.tid index ef0022cc6..8daad0f10 100755 --- a/core/images/heading-2.tid +++ b/core/images/heading-2.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-2 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-2 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-3.tid b/core/images/heading-3.tid index d706d067b..8a489e799 100755 --- a/core/images/heading-3.tid +++ b/core/images/heading-3.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-3 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-3 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-4.tid b/core/images/heading-4.tid index 16d4440db..5aee3f3f8 100755 --- a/core/images/heading-4.tid +++ b/core/images/heading-4.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-4 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-4 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-5.tid b/core/images/heading-5.tid index 8f34b7058..c9a54a335 100755 --- a/core/images/heading-5.tid +++ b/core/images/heading-5.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-5 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-5 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/heading-6.tid b/core/images/heading-6.tid index b348c70af..1034e7116 100755 --- a/core/images/heading-6.tid +++ b/core/images/heading-6.tid @@ -1,4 +1,5 @@ title: $:/core/images/heading-6 tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-heading-6 tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/help.tid b/core/images/help.tid index 07167ae93..5c0cf13ab 100755 --- a/core/images/help.tid +++ b/core/images/help.tid @@ -1,4 +1,5 @@ title: $:/core/images/help tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-help tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/home-button.tid b/core/images/home-button.tid index 10c00626a..952ab9a60 100755 --- a/core/images/home-button.tid +++ b/core/images/home-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/home-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-home-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/import-button.tid b/core/images/import-button.tid index 6850513ef..a42c416e5 100755 --- a/core/images/import-button.tid +++ b/core/images/import-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/import-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-import-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/info-button.tid b/core/images/info-button.tid index 2679a135a..e8f8e98c4 100755 --- a/core/images/info-button.tid +++ b/core/images/info-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/info-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-info-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/italic.tid b/core/images/italic.tid index 06aada589..766d3707a 100755 --- a/core/images/italic.tid +++ b/core/images/italic.tid @@ -1,4 +1,5 @@ title: $:/core/images/italic tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-italic tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/layout-button.tid b/core/images/layout-button.tid new file mode 100755 index 000000000..a859edbc5 --- /dev/null +++ b/core/images/layout-button.tid @@ -0,0 +1,5 @@ +title: $:/core/images/layout-button +tags: $:/tags/Image + +\parameters (size:"22pt") +> height=<> class="tc-image-layout-button tc-image-button" viewBox="0 0 24 24" stroke-width="1" stroke="none"> \ No newline at end of file diff --git a/core/images/left-arrow.tid b/core/images/left-arrow.tid index a418581cd..b64fc2ab6 100755 --- a/core/images/left-arrow.tid +++ b/core/images/left-arrow.tid @@ -3,4 +3,5 @@ modified: 20150315235324760 tags: $:/tags/Image title: $:/core/images/left-arrow - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-left-arrow tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/line-width.tid b/core/images/line-width.tid index f77763ce6..9cecc33cb 100755 --- a/core/images/line-width.tid +++ b/core/images/line-width.tid @@ -1,4 +1,5 @@ title: $:/core/images/line-width tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-line-width tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/link.tid b/core/images/link.tid index 395307c42..c1d134f7e 100644 --- a/core/images/link.tid +++ b/core/images/link.tid @@ -1,4 +1,5 @@ title: $:/core/images/link tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-link tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/linkify.tid b/core/images/linkify.tid index 40acdc19a..d616c2ac9 100644 --- a/core/images/linkify.tid +++ b/core/images/linkify.tid @@ -1,4 +1,5 @@ title: $:/core/images/linkify tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-linkify-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/list-bullet.tid b/core/images/list-bullet.tid index 322dd4ae6..065d96c4f 100755 --- a/core/images/list-bullet.tid +++ b/core/images/list-bullet.tid @@ -1,4 +1,5 @@ title: $:/core/images/list-bullet tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-list-bullet tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/list-number.tid b/core/images/list-number.tid index 161917823..b70d4db15 100755 --- a/core/images/list-number.tid +++ b/core/images/list-number.tid @@ -1,4 +1,5 @@ title: $:/core/images/list-number tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-list-number tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/list.tid b/core/images/list.tid index 22b784bfe..793b47957 100644 --- a/core/images/list.tid +++ b/core/images/list.tid @@ -1,4 +1,5 @@ title: $:/core/images/list tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-list tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/locked-padlock.tid b/core/images/locked-padlock.tid index 14d95560c..f6722cddd 100755 --- a/core/images/locked-padlock.tid +++ b/core/images/locked-padlock.tid @@ -1,4 +1,5 @@ title: $:/core/images/locked-padlock tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-locked-padlock tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/mail.tid b/core/images/mail.tid index cf0f4eab7..9d46d6eff 100755 --- a/core/images/mail.tid +++ b/core/images/mail.tid @@ -1,4 +1,5 @@ title: $:/core/images/mail tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-mail tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/mastodon.tid b/core/images/mastodon.tid new file mode 100644 index 000000000..a6b41d355 --- /dev/null +++ b/core/images/mastodon.tid @@ -0,0 +1,7 @@ +title: $:/core/images/mastodon +tags: $:/tags/Image + +\parameters (size:"22pt") +> height=<> class="tc-image-mastodon tc-image-button" viewBox="0 0 128 128"> + + diff --git a/core/images/menu-button.tid b/core/images/menu-button.tid index 6d1872e4c..958721d31 100755 --- a/core/images/menu-button.tid +++ b/core/images/menu-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/menu-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-menu-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/minus-button.tid b/core/images/minus-button.tid index 7132ed3e9..40ee75a8e 100644 --- a/core/images/minus-button.tid +++ b/core/images/minus-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/minus-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-minus-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/mono-block.tid b/core/images/mono-block.tid index f8695302b..bf58400aa 100755 --- a/core/images/mono-block.tid +++ b/core/images/mono-block.tid @@ -1,4 +1,5 @@ title: $:/core/images/mono-block tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-mono-block tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/mono-line.tid b/core/images/mono-line.tid index 09cfe513e..1ab73b829 100755 --- a/core/images/mono-line.tid +++ b/core/images/mono-line.tid @@ -1,4 +1,5 @@ title: $:/core/images/mono-line tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-mono-line tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/network-activity.tid b/core/images/network-activity.tid new file mode 100644 index 000000000..2efdfd4d4 --- /dev/null +++ b/core/images/network-activity.tid @@ -0,0 +1,11 @@ +title: $:/core/images/network-activity +tags: $:/tags/Image + + +<$list filter="[{$:/state/http-requests}match[0]]" variable="ignore"> + + +<$list filter="[{$:/state/http-requests}!match[0]]" variable="ignore"> + + + \ No newline at end of file diff --git a/core/images/new-button.tid b/core/images/new-button.tid index 6e592ada9..d4cfd34f6 100755 --- a/core/images/new-button.tid +++ b/core/images/new-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/new-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-new-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/new-here-button.tid b/core/images/new-here-button.tid index ab0f7a6f3..8e304f5e7 100755 --- a/core/images/new-here-button.tid +++ b/core/images/new-here-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/new-here-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-new-here-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/new-image-button.tid b/core/images/new-image-button.tid index 16b63c3c3..53b10d481 100755 --- a/core/images/new-image-button.tid +++ b/core/images/new-image-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/new-image-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-new-image-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/new-journal-button.tid b/core/images/new-journal-button.tid index fb67c8007..5b793deb5 100755 --- a/core/images/new-journal-button.tid +++ b/core/images/new-journal-button.tid @@ -1,4 +1,4 @@ title: $:/core/images/new-journal-button tags: $:/tags/Image -<> \ No newline at end of file +<$parameters size="22pt" day=<>>> height=<> class="tc-image-new-journal-button tc-image-button" viewBox="0 0 128 128"><$text text=<>/> \ No newline at end of file diff --git a/core/images/opacity.tid b/core/images/opacity.tid index e9a29aea2..0211644f9 100755 --- a/core/images/opacity.tid +++ b/core/images/opacity.tid @@ -1,4 +1,5 @@ title: $:/core/images/opacity tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-opacity tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/open-window.tid b/core/images/open-window.tid index 14b556484..d918b1fc8 100755 --- a/core/images/open-window.tid +++ b/core/images/open-window.tid @@ -1,4 +1,5 @@ title: $:/core/images/open-window tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-open-window tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/options-button.tid b/core/images/options-button.tid index bd0ffcb1a..18fbf8b00 100755 --- a/core/images/options-button.tid +++ b/core/images/options-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/options-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-options-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/paint.tid b/core/images/paint.tid index bb536b53a..660fda2bf 100755 --- a/core/images/paint.tid +++ b/core/images/paint.tid @@ -1,4 +1,5 @@ title: $:/core/images/paint tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-paint tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/palette.tid b/core/images/palette.tid index d605fd853..1c7903549 100755 --- a/core/images/palette.tid +++ b/core/images/palette.tid @@ -1,4 +1,5 @@ title: $:/core/images/palette tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-palette tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/permalink-button.tid b/core/images/permalink-button.tid index e8fd0aecd..f1cf38b41 100755 --- a/core/images/permalink-button.tid +++ b/core/images/permalink-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/permalink-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-permalink-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/permaview-button.tid b/core/images/permaview-button.tid index b2ad9a408..82e533475 100755 --- a/core/images/permaview-button.tid +++ b/core/images/permaview-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/permaview-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-permaview-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/picture.tid b/core/images/picture.tid index 7d035e2fc..2af427e2e 100755 --- a/core/images/picture.tid +++ b/core/images/picture.tid @@ -1,4 +1,5 @@ title: $:/core/images/picture tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-picture tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/plugin-generic-language.tid b/core/images/plugin-generic-language.tid index 5c777d98d..d663d1563 100755 --- a/core/images/plugin-generic-language.tid +++ b/core/images/plugin-generic-language.tid @@ -1,4 +1,5 @@ title: $:/core/images/plugin-generic-language tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> viewBox="0 0 128 128" class="tc-image-plugin-generic-language tc-image-button"> \ No newline at end of file diff --git a/core/images/plugin-generic-plugin.tid b/core/images/plugin-generic-plugin.tid index ab2e6670e..06073dd7c 100755 --- a/core/images/plugin-generic-plugin.tid +++ b/core/images/plugin-generic-plugin.tid @@ -1,4 +1,5 @@ title: $:/core/images/plugin-generic-plugin tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> viewBox="0 0 128 128" class="tc-image-plugin-generic-plugin tc-image-button"> \ No newline at end of file diff --git a/core/images/plugin-generic-theme.tid b/core/images/plugin-generic-theme.tid index 9ae3cd779..ab899b3e4 100755 --- a/core/images/plugin-generic-theme.tid +++ b/core/images/plugin-generic-theme.tid @@ -1,4 +1,5 @@ title: $:/core/images/plugin-generic-theme tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> viewBox="0 0 128 128" class="tc-image-plugin-generic-theme tc-image-button"> \ No newline at end of file diff --git a/core/images/plus-button.tid b/core/images/plus-button.tid index b001f3e2f..c9a696d43 100644 --- a/core/images/plus-button.tid +++ b/core/images/plus-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/plus-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-plus-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/preview-closed.tid b/core/images/preview-closed.tid index 5986d8966..cf17730d5 100755 --- a/core/images/preview-closed.tid +++ b/core/images/preview-closed.tid @@ -1,4 +1,5 @@ title: $:/core/images/preview-closed tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-preview-closed tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/preview-open.tid b/core/images/preview-open.tid index 4664990b4..cb30bf474 100755 --- a/core/images/preview-open.tid +++ b/core/images/preview-open.tid @@ -1,4 +1,5 @@ title: $:/core/images/preview-open tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-preview-open tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/print-button.tid b/core/images/print-button.tid index 55b33c896..12bffd41d 100644 --- a/core/images/print-button.tid +++ b/core/images/print-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/print-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-print-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/quote.tid b/core/images/quote.tid index 7134306a6..0c4fcf25a 100755 --- a/core/images/quote.tid +++ b/core/images/quote.tid @@ -1,4 +1,5 @@ title: $:/core/images/quote tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-quote tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/refresh-button.tid b/core/images/refresh-button.tid index 2422b0679..f8e3fc69e 100755 --- a/core/images/refresh-button.tid +++ b/core/images/refresh-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/refresh-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-refresh-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/right-arrow.tid b/core/images/right-arrow.tid index 42e7dea56..64f839b55 100755 --- a/core/images/right-arrow.tid +++ b/core/images/right-arrow.tid @@ -1,4 +1,5 @@ title: $:/core/images/right-arrow tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-right-arrow tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/rotate-left.tid b/core/images/rotate-left.tid index 188d3b45c..da6034b19 100644 --- a/core/images/rotate-left.tid +++ b/core/images/rotate-left.tid @@ -1,4 +1,5 @@ title: $:/core/images/rotate-left tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-rotate-left tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/save-button-dynamic.tid b/core/images/save-button-dynamic.tid new file mode 100644 index 000000000..7a351d617 --- /dev/null +++ b/core/images/save-button-dynamic.tid @@ -0,0 +1,13 @@ +title: $:/core/images/save-button-dynamic +tags: $:/tags/Image + +\parameters (size:"22pt") +> height=<> class="tc-image-save-button-dynamic tc-image-button" viewBox="0 0 128 128"> + + + + + + + + \ No newline at end of file diff --git a/core/images/save-button.tid b/core/images/save-button.tid index a66756616..912ad248c 100755 --- a/core/images/save-button.tid +++ b/core/images/save-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/save-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-save-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/size.tid b/core/images/size.tid index db84ecf9b..ea9aa1094 100755 --- a/core/images/size.tid +++ b/core/images/size.tid @@ -1,4 +1,5 @@ title: $:/core/images/size tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-size tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/spiral.tid b/core/images/spiral.tid index ca4684cab..f3a5271ac 100755 --- a/core/images/spiral.tid +++ b/core/images/spiral.tid @@ -1,4 +1,5 @@ title: $:/core/images/spiral tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-spiral tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/stamp.tid b/core/images/stamp.tid index ba385aaae..8511a457f 100755 --- a/core/images/stamp.tid +++ b/core/images/stamp.tid @@ -1,4 +1,5 @@ title: $:/core/images/stamp tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-stamp tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/star-filled.tid b/core/images/star-filled.tid index 10b8f1c3d..262448d51 100755 --- a/core/images/star-filled.tid +++ b/core/images/star-filled.tid @@ -1,4 +1,5 @@ title: $:/core/images/star-filled tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-star-filled tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/storyview-classic.tid b/core/images/storyview-classic.tid index 86872817b..457434bc9 100755 --- a/core/images/storyview-classic.tid +++ b/core/images/storyview-classic.tid @@ -1,4 +1,5 @@ title: $:/core/images/storyview-classic tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-storyview-classic tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/storyview-pop.tid b/core/images/storyview-pop.tid index a610c89d5..a4a9fb9ee 100755 --- a/core/images/storyview-pop.tid +++ b/core/images/storyview-pop.tid @@ -1,4 +1,5 @@ title: $:/core/images/storyview-pop tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-storyview-pop tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/storyview-zoomin.tid b/core/images/storyview-zoomin.tid index 61b7ff273..725f36e71 100755 --- a/core/images/storyview-zoomin.tid +++ b/core/images/storyview-zoomin.tid @@ -1,4 +1,5 @@ title: $:/core/images/storyview-zoomin tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-storyview-zoomin tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/strikethrough.tid b/core/images/strikethrough.tid index 1f7a1c202..de4eefeec 100755 --- a/core/images/strikethrough.tid +++ b/core/images/strikethrough.tid @@ -1,4 +1,5 @@ title: $:/core/images/strikethrough tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-strikethrough tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/subscript.tid b/core/images/subscript.tid index 96548bdb5..76ec35399 100755 --- a/core/images/subscript.tid +++ b/core/images/subscript.tid @@ -1,4 +1,5 @@ title: $:/core/images/subscript tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-subscript tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/superscript.tid b/core/images/superscript.tid index 149e44893..ab0d0d1b2 100755 --- a/core/images/superscript.tid +++ b/core/images/superscript.tid @@ -1,4 +1,5 @@ title: $:/core/images/superscript tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-superscript tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/tag-button.tid b/core/images/tag-button.tid index 9f6cad8b4..ab407f780 100755 --- a/core/images/tag-button.tid +++ b/core/images/tag-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/tag-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-tag-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/theme-button.tid b/core/images/theme-button.tid index d80a0e82a..6b7aab2af 100755 --- a/core/images/theme-button.tid +++ b/core/images/theme-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/theme-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-theme-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/timestamp-off.tid b/core/images/timestamp-off.tid index 0d20f28d6..33e018f3a 100644 --- a/core/images/timestamp-off.tid +++ b/core/images/timestamp-off.tid @@ -1,4 +1,5 @@ title: $:/core/images/timestamp-off tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-timestamp-off tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/timestamp-on.tid b/core/images/timestamp-on.tid index 3a16df7eb..cad04aada 100644 --- a/core/images/timestamp-on.tid +++ b/core/images/timestamp-on.tid @@ -1,4 +1,5 @@ title: $:/core/images/timestamp-on tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-timestamp-on tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/tip.tid b/core/images/tip.tid index f8109ada4..025918306 100755 --- a/core/images/tip.tid +++ b/core/images/tip.tid @@ -1,4 +1,5 @@ title: $:/core/images/tip tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-tip tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/transcludify.tid b/core/images/transcludify.tid index 0579feb10..5102d1370 100644 --- a/core/images/transcludify.tid +++ b/core/images/transcludify.tid @@ -1,4 +1,5 @@ title: $:/core/images/transcludify tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-transcludify-button tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/twitter.tid b/core/images/twitter.tid index 28cfccdbd..e3ae13dc1 100755 --- a/core/images/twitter.tid +++ b/core/images/twitter.tid @@ -1,4 +1,5 @@ title: $:/core/images/twitter tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-twitter tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/underline.tid b/core/images/underline.tid index 768d2a199..341b27cfa 100755 --- a/core/images/underline.tid +++ b/core/images/underline.tid @@ -1,4 +1,5 @@ title: $:/core/images/underline tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-underline tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/unfold-all-button.tid b/core/images/unfold-all-button.tid index e496bdd89..e44000b18 100755 --- a/core/images/unfold-all-button.tid +++ b/core/images/unfold-all-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/unfold-all-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-unfold-all tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/unfold-button.tid b/core/images/unfold-button.tid index cfad70570..57f53fd6f 100755 --- a/core/images/unfold-button.tid +++ b/core/images/unfold-button.tid @@ -1,4 +1,5 @@ title: $:/core/images/unfold-button tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-unfold tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/unlocked-padlock.tid b/core/images/unlocked-padlock.tid index c5367c085..941f7bec5 100755 --- a/core/images/unlocked-padlock.tid +++ b/core/images/unlocked-padlock.tid @@ -1,4 +1,5 @@ title: $:/core/images/unlocked-padlock tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-unlocked-padlock tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/up-arrow.tid b/core/images/up-arrow.tid index a1bd132bf..4d157352b 100755 --- a/core/images/up-arrow.tid +++ b/core/images/up-arrow.tid @@ -3,4 +3,5 @@ modified: 20150316000831867 tags: $:/tags/Image title: $:/core/images/up-arrow - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-up-arrow tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/video.tid b/core/images/video.tid index 3bf0bb259..b4fef628d 100755 --- a/core/images/video.tid +++ b/core/images/video.tid @@ -1,4 +1,5 @@ title: $:/core/images/video tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-video tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/images/warning.tid b/core/images/warning.tid index 53bff59ec..1822da89f 100755 --- a/core/images/warning.tid +++ b/core/images/warning.tid @@ -1,4 +1,5 @@ title: $:/core/images/warning tags: $:/tags/Image - \ No newline at end of file +\parameters (size:"22pt") +> height=<> class="tc-image-warning tc-image-button" viewBox="0 0 128 128"> \ No newline at end of file diff --git a/core/language/en-GB/Buttons.multids b/core/language/en-GB/Buttons.multids index 7cf1c9955..fa769d117 100644 --- a/core/language/en-GB/Buttons.multids +++ b/core/language/en-GB/Buttons.multids @@ -59,12 +59,16 @@ Home/Caption: home Home/Hint: Open the default tiddlers Language/Caption: language Language/Hint: Choose the user interface language +LayoutSwitcher/Hint: Open layout switcher +LayoutSwitcher/Caption: layout Manager/Caption: tiddler manager Manager/Hint: Open tiddler manager More/Caption: more More/Hint: More actions NewHere/Caption: new here NewHere/Hint: Create a new tiddler tagged with this one +NetworkActivity/Caption: network activity +NetworkActivity/Hint: Cancel all network activity NewJournal/Caption: new journal NewJournal/Hint: Create a new journal tiddler NewJournalHere/Caption: new journal here diff --git a/core/language/en-GB/ControlPanel.multids b/core/language/en-GB/ControlPanel.multids index ca1739b76..d8321edbf 100644 --- a/core/language/en-GB/ControlPanel.multids +++ b/core/language/en-GB/ControlPanel.multids @@ -90,8 +90,8 @@ Plugins/Languages/Caption: Languages Plugins/Languages/Hint: Language pack plugins Plugins/NoInfoFound/Hint: No ''"<$text text=<>/>"'' found Plugins/NotInstalled/Hint: This plugin is not currently installed -Plugins/OpenPluginLibrary: open plugin library -Plugins/ClosePluginLibrary: close plugin library +Plugins/OpenPluginLibrary: Open plugin library +Plugins/ClosePluginLibrary: Close plugin library Plugins/PluginWillRequireReload: (requires reload) Plugins/Plugins/Caption: Plugins Plugins/Plugins/Hint: Plugins diff --git a/core/language/en-GB/Exporters.multids b/core/language/en-GB/Exporters.multids index e455b8bf1..6ac52efe7 100644 --- a/core/language/en-GB/Exporters.multids +++ b/core/language/en-GB/Exporters.multids @@ -3,4 +3,4 @@ title: $:/language/Exporters/ StaticRiver: Static HTML JsonFile: JSON file CsvFile: CSV file -TidFile: ".tid" file +TidFile: TID text file diff --git a/core/language/en-GB/Fields.multids b/core/language/en-GB/Fields.multids index c094580d5..68804f082 100644 --- a/core/language/en-GB/Fields.multids +++ b/core/language/en-GB/Fields.multids @@ -1,11 +1,14 @@ title: $:/language/Docs/Fields/ _canonical_uri: The full URI of an external image tiddler +author: Name of the author of a plugin bag: The name of the bag from which a tiddler came caption: The text to be displayed on a tab or button +class: The CSS class applied to a tiddler when rendering it - see [[Custom styles by user-class]]. Also used for [[Modals]] code-body: The view template will display the tiddler as code if set to ''yes'' color: The CSS color value associated with a tiddler component: The name of the component responsible for an [[alert tiddler|AlertMechanism]] +core-version: For a plugin, indicates what version of TiddlyWiki with which it is compatible current-tiddler: Used to cache the top tiddler in a [[history list|HistoryMechanism]] created: The date a tiddler was created creator: The name of the person who created a tiddler @@ -22,7 +25,9 @@ list-before: If set, the title of a tiddler before which this tiddler should be list-after: If set, the title of the tiddler after which this tiddler should be added to the ordered list of tiddler titles, or at the end of the list if this field is present but empty modified: The date and time at which a tiddler was last modified modifier: The tiddler title associated with the person who last modified a tiddler +module-type: For javascript tiddlers, specifies what kind of module it is name: The human readable name associated with a plugin tiddler +parent-plugin: For a plugin, specifies which plugin of which it is a sub-plugin plugin-priority: A numerical value indicating the priority of a plugin tiddler plugin-type: The type of plugin in a plugin tiddler revision: The revision of the tiddler held at the server diff --git a/core/language/en-GB/Help/commands.tid b/core/language/en-GB/Help/commands.tid new file mode 100644 index 000000000..7551885f0 --- /dev/null +++ b/core/language/en-GB/Help/commands.tid @@ -0,0 +1,18 @@ +title: $:/language/Help/commands +description: Run commands returned from a filter + +Sequentially run the command tokens returned from a filter + +``` +--commands +``` + +Examples + +``` +--commands "[enlist:raw{$:/build-commands-as-text}]" +``` + +``` +--commands "[{$:/build-commands-as-json}jsonindexes[]] :map[{$:/build-commands-as-json}jsonget]" +``` diff --git a/core/language/en-GB/Help/listen.tid b/core/language/en-GB/Help/listen.tid index 45df72381..d9f6a247f 100644 --- a/core/language/en-GB/Help/listen.tid +++ b/core/language/en-GB/Help/listen.tid @@ -18,7 +18,7 @@ All parameters are optional with safe defaults, and can be specified in any orde * ''anon-username'' - the username for signing edits for anonymous users * ''username'' - optional username for basic authentication * ''password'' - optional password for basic authentication -* ''authenticated-user-header'' - optional name of header to be used for trusted authentication +* ''authenticated-user-header'' - optional name of request header to be used for trusted authentication. * ''readers'' - comma-separated list of principals allowed to read from this wiki * ''writers'' - comma-separated list of principals allowed to write to this wiki * ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no") diff --git a/core/language/en-GB/Help/savewikifolder.tid b/core/language/en-GB/Help/savewikifolder.tid index bda1d19a3..82565f7bc 100644 --- a/core/language/en-GB/Help/savewikifolder.tid +++ b/core/language/en-GB/Help/savewikifolder.tid @@ -4,7 +4,7 @@ description: Saves a wiki to a new wiki folder <<.from-version "5.1.20">> Saves the current wiki as a wiki folder, including tiddlers, plugins and configuration: ``` ---savewikifolder [] +--savewikifolder [] [ [=] ]* ``` * The target wiki folder must be empty or non-existent @@ -12,8 +12,23 @@ description: Saves a wiki to a new wiki folder * Plugins from the official plugin library are replaced with references to those plugins in the `tiddlywiki.info` file * Custom plugins are unpacked into their own folder +The following options are supported: + +* ''filter'': a filter expression that defines the tiddlers to include in the output. +* ''explodePlugins'': defaults to "yes" +** ''yes'' will "explode" plugins into separate tiddler files and save them to the plugin directory within the wiki folder +** ''no'' will suppress exploding plugins into their constituent tiddler files. It will save the plugin as a single JSON tiddler in the tiddlers folder + +Note that both ''explodePlugins'' options will produce wiki folders that build the exact same original wiki. The difference lies in how plugins are represented in the wiki folder. + A common usage is to convert a TiddlyWiki HTML file into a wiki folder: ``` tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder ``` + +Save the plugin to the tiddlers directory of the target wiki folder: + +``` +tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder explodePlugins=no +``` diff --git a/core/language/en-GB/Help/server.tid b/core/language/en-GB/Help/server.tid index 78e9c8ab1..da6865031 100644 --- a/core/language/en-GB/Help/server.tid +++ b/core/language/en-GB/Help/server.tid @@ -1,5 +1,5 @@ title: $:/language/Help/server -description: Provides an HTTP server interface to TiddlyWiki (deprecated in favour of the new listen command) +description: (deprecated: see 'listen' command) Provides an HTTP server interface to TiddlyWiki Legacy command to serve a wiki over HTTP. diff --git a/core/language/en-GB/Misc.multids b/core/language/en-GB/Misc.multids index 00cb3c99c..2c10d1acb 100644 --- a/core/language/en-GB/Misc.multids +++ b/core/language/en-GB/Misc.multids @@ -25,6 +25,8 @@ Encryption/RepeatPassword: Repeat password Encryption/PasswordNoMatch: Passwords do not match Encryption/SetPassword: Set password Error/Caption: Error +Error/DeserializeOperator/MissingOperand: Filter Error: Missing operand for 'deserialize' operator +Error/DeserializeOperator/UnknownDeserializer: Filter Error: Unknown deserializer provided as operand for the 'deserialize' operator Error/Filter: Filter error Error/FilterSyntax: Syntax error in filter expression Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run @@ -40,6 +42,7 @@ Error/RetrievingSkinny: Error retrieving skinny tiddler list Error/SavingToTWEdit: Error saving to TWEdit Error/WhileSaving: Error while saving Error/XMLHttpRequest: XMLHttpRequest error code +Error/ZoominTextNode: Story View Error: It appears you tried to interact with a tiddler that displays in a custom container. This is most likely caused by using `$:/tags/StoryTiddlerTemplateFilter` with a template that contains text or whitespace at the start. Please use the pragma `\whitespace trim` and ensure the whole contents of the tiddler is wrapped in a single HTML element. The text that caused this issue: InternalJavaScriptError/Title: Internal JavaScript Error InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser LayoutSwitcher/Description: Open the layout switcher diff --git a/core/language/en-GB/Modals/SaveInstructions.tid b/core/language/en-GB/Modals/SaveInstructions.tid deleted file mode 100644 index 45028fc45..000000000 --- a/core/language/en-GB/Modals/SaveInstructions.tid +++ /dev/null @@ -1,21 +0,0 @@ -title: $:/language/Modals/SaveInstructions -subtitle: Save your work -footer: <$button message="tm-close-tiddler">Close -help: https://tiddlywiki.com/static/SavingChanges.html - -Your changes to this wiki need to be saved as a ~TiddlyWiki HTML file. - -!!! Desktop browsers - -# Select ''Save As'' from the ''File'' menu -# Choose a filename and location -#* Some browsers also require you to explicitly specify the file saving format as ''Webpage, HTML only'' or similar -# Close this tab - -!!! Smartphone browsers - -# Create a bookmark to this page -#* If you've got iCloud or Google Sync set up then the bookmark will automatically sync to your desktop where you can open it and save it as above -# Close this tab - -//If you open the bookmark again in Mobile Safari you will see this message again. If you want to go ahead and use the file, just click the ''close'' button below// diff --git a/core/language/en-GB/SiteTitle.tid b/core/language/en-GB/SiteTitle.tid index 9f522664a..a32da7dfe 100644 --- a/core/language/en-GB/SiteTitle.tid +++ b/core/language/en-GB/SiteTitle.tid @@ -1,3 +1,3 @@ title: $:/SiteTitle -My ~TiddlyWiki \ No newline at end of file +My TiddlyWiki \ No newline at end of file diff --git a/core/language/en-GB/Types/image_svg_xml.tid b/core/language/en-GB/Types/image_svg_xml.tid index 9f7c23ba3..94c3ea949 100644 --- a/core/language/en-GB/Types/image_svg_xml.tid +++ b/core/language/en-GB/Types/image_svg_xml.tid @@ -1,5 +1,5 @@ title: $:/language/Docs/Types/image/svg+xml -description: Structured Vector Graphics image +description: SVG image name: image/svg+xml group: Image group-sort: 1 diff --git a/core/language/en-GB/Types/image_x-icon.tid b/core/language/en-GB/Types/image_x-icon.tid index 6ae32331c..55420387a 100644 --- a/core/language/en-GB/Types/image_x-icon.tid +++ b/core/language/en-GB/Types/image_x-icon.tid @@ -1,5 +1,5 @@ title: $:/language/Docs/Types/image/x-icon -description: ICO format icon file +description: ICO icon name: image/x-icon group: Image group-sort: 1 diff --git a/core/modules/commands/commands.js b/core/modules/commands/commands.js new file mode 100644 index 000000000..813f19064 --- /dev/null +++ b/core/modules/commands/commands.js @@ -0,0 +1,42 @@ +/*\ +title: $:/core/modules/commands/commands.js +type: application/javascript +module-type: command + +Runs the commands returned from a filter + +\*/ + +(function() { + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.info = { + name: "commands", + synchronous: true +}; + +var Command = function(params, commander) { + this.params = params; + this.commander = commander; +}; + +Command.prototype.execute = function() { + // Parse the filter + var filter = this.params[0]; + if(!filter) { + return "No filter specified"; + } + var commands = this.commander.wiki.filterTiddlers(filter) + if(commands.length === 0) { + return "No tiddlers found for filter '" + filter + "'"; + } + this.commander.addCommandTokens(commands); + return null; +}; + +exports.Command = Command; + +})(); diff --git a/core/modules/commands/rendertiddlers.js b/core/modules/commands/rendertiddlers.js index 91030b0f3..78272cc33 100644 --- a/core/modules/commands/rendertiddlers.js +++ b/core/modules/commands/rendertiddlers.js @@ -57,7 +57,7 @@ Command.prototype.execute = function() { exportPath = path.resolve(outputPath,macroPath + extension); } } - var finalPath = exportPath || path.resolve(pathname,encodeURIComponent(title) + extension); + var finalPath = exportPath || path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title) + extension); $tw.utils.createFileDirectories(finalPath); fs.writeFileSync(finalPath,text,"utf8"); }); diff --git a/core/modules/commands/savelibrarytiddlers.js b/core/modules/commands/savelibrarytiddlers.js index 07521f3ba..af42d7c8a 100644 --- a/core/modules/commands/savelibrarytiddlers.js +++ b/core/modules/commands/savelibrarytiddlers.js @@ -65,7 +65,7 @@ Command.prototype.execute = function() { $tw.utils.each(filteredPluginList,function(title) { var tiddler = containerData.tiddlers[title]; // Save each JSON file and collect the skinny data - var pathname = path.resolve(self.commander.outputPath,basepath + encodeURIComponent(title) + ".json"); + var pathname = path.resolve(self.commander.outputPath,basepath + $tw.utils.encodeURIComponentExtended(title) + ".json"); $tw.utils.createFileDirectories(pathname); fs.writeFileSync(pathname,JSON.stringify(tiddler),"utf8"); // Collect the skinny list data diff --git a/core/modules/commands/savetiddlers.js b/core/modules/commands/savetiddlers.js index de29efdb7..9c750e204 100644 --- a/core/modules/commands/savetiddlers.js +++ b/core/modules/commands/savetiddlers.js @@ -45,8 +45,8 @@ Command.prototype.execute = function() { var tiddler = self.commander.wiki.getTiddler(title), type = tiddler.fields.type || "text/vnd.tiddlywiki", contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"}, - filename = path.resolve(pathname,encodeURIComponent(title)); - fs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding); + filename = path.resolve(pathname,$tw.utils.encodeURIComponentExtended(title)); + fs.writeFileSync(filename,tiddler.fields.text || "",contentTypeInfo.encoding); }); return null; }; diff --git a/core/modules/commands/savewikifolder.js b/core/modules/commands/savewikifolder.js index 48e9be56a..c0fccd775 100644 --- a/core/modules/commands/savewikifolder.js +++ b/core/modules/commands/savewikifolder.js @@ -5,7 +5,14 @@ module-type: command Command to save the current wiki as a wiki folder ---savewikifolder [] +--savewikifolder [ [=] ]* + +The following options are supported: + +* ''filter'': a filter expression defining the tiddlers to be included in the output +* ''explodePlugins'': set to "no" to suppress exploding plugins into their constituent shadow tiddlers (defaults to "yes") + +Supports backward compatibility with --savewikifolder [] [ [=] ]* \*/ (function(){ @@ -35,14 +42,28 @@ Command.prototype.execute = function() { if(this.params.length < 1) { return "Missing wiki folder path"; } - var wikifoldermaker = new WikiFolderMaker(this.params[0],this.params[1],this.commander); + var regFilter = /^[a-zA-Z0-9\.\-_]+=/g, // dynamic parameters + namedParames, + tiddlerFilter, + options = {}; + if (regFilter.test(this.params[1])) { + namedParames = this.commander.extractNamedParameters(this.params.slice(1)); + tiddlerFilter = namedParames.filter || "[all[tiddlers]]"; + } else { + namedParames = this.commander.extractNamedParameters(this.params.slice(2)); + tiddlerFilter = this.params[1]; + } + tiddlerFilter = tiddlerFilter || "[all[tiddlers]]"; + options.explodePlugins = namedParames.explodePlugins || "yes"; + var wikifoldermaker = new WikiFolderMaker(this.params[0],tiddlerFilter,this.commander,options); return wikifoldermaker.save(); }; -function WikiFolderMaker(wikiFolderPath,wikiFilter,commander) { +function WikiFolderMaker(wikiFolderPath,wikiFilter,commander,options) { this.wikiFolderPath = wikiFolderPath; - this.wikiFilter = wikiFilter || "[all[tiddlers]]"; + this.wikiFilter = wikiFilter; this.commander = commander; + this.explodePlugins = options.explodePlugins; this.wiki = commander.wiki; this.savedPaths = []; // So that we can detect filename clashes } @@ -93,10 +114,13 @@ WikiFolderMaker.prototype.save = function() { self.log("Adding built-in plugin: " + libraryDetails.name); newWikiInfo[libraryDetails.type] = newWikiInfo[libraryDetails.type] || []; $tw.utils.pushTop(newWikiInfo[libraryDetails.type],libraryDetails.name); - } else { + } else if(self.explodePlugins !== "no") { // A custom plugin self.log("Processing custom plugin: " + title); self.saveCustomPlugin(tiddler); + } else if(self.explodePlugins === "no") { + self.log("Processing custom plugin to tiddlders folder: " + title); + self.saveTiddler("tiddlers", tiddler); } } else { // Ordinary tiddler diff --git a/core/modules/config.js b/core/modules/config.js index 77e74edf8..399af598b 100644 --- a/core/modules/config.js +++ b/core/modules/config.js @@ -30,7 +30,7 @@ exports.textPrimitives.wikiLink = exports.textPrimitives.upperLetter + "+" + exports.textPrimitives.upperLetter + exports.textPrimitives.anyLetter + "*"; -exports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 }; +exports.htmlEntities = {quot:34, dollar:36, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:161, cent:162, pound:163, curren:164, yen:165, brvbar:166, sect:167, uml:168, copy:169, ordf:170, laquo:171, not:172, shy:173, reg:174, macr:175, deg:176, plusmn:177, sup2:178, sup3:179, acute:180, micro:181, para:182, middot:183, cedil:184, sup1:185, ordm:186, raquo:187, frac14:188, frac12:189, frac34:190, iquest:191, Agrave:192, Aacute:193, Acirc:194, Atilde:195, Auml:196, Aring:197, AElig:198, Ccedil:199, Egrave:200, Eacute:201, Ecirc:202, Euml:203, Igrave:204, Iacute:205, Icirc:206, Iuml:207, ETH:208, Ntilde:209, Ograve:210, Oacute:211, Ocirc:212, Otilde:213, Ouml:214, times:215, Oslash:216, Ugrave:217, Uacute:218, Ucirc:219, Uuml:220, Yacute:221, THORN:222, szlig:223, agrave:224, aacute:225, acirc:226, atilde:227, auml:228, aring:229, aelig:230, ccedil:231, egrave:232, eacute:233, ecirc:234, euml:235, igrave:236, iacute:237, icirc:238, iuml:239, eth:240, ntilde:241, ograve:242, oacute:243, ocirc:244, otilde:245, ouml:246, divide:247, oslash:248, ugrave:249, uacute:250, ucirc:251, uuml:252, yacute:253, thorn:254, yuml:255, OElig:338, oelig:339, Scaron:352, scaron:353, Yuml:376, fnof:402, circ:710, tilde:732, Alpha:913, Beta:914, Gamma:915, Delta:916, Epsilon:917, Zeta:918, Eta:919, Theta:920, Iota:921, Kappa:922, Lambda:923, Mu:924, Nu:925, Xi:926, Omicron:927, Pi:928, Rho:929, Sigma:931, Tau:932, Upsilon:933, Phi:934, Chi:935, Psi:936, Omega:937, alpha:945, beta:946, gamma:947, delta:948, epsilon:949, zeta:950, eta:951, theta:952, iota:953, kappa:954, lambda:955, mu:956, nu:957, xi:958, omicron:959, pi:960, rho:961, sigmaf:962, sigma:963, tau:964, upsilon:965, phi:966, chi:967, psi:968, omega:969, thetasym:977, upsih:978, piv:982, ensp:8194, emsp:8195, thinsp:8201, zwnj:8204, zwj:8205, lrm:8206, rlm:8207, ndash:8211, mdash:8212, lsquo:8216, rsquo:8217, sbquo:8218, ldquo:8220, rdquo:8221, bdquo:8222, dagger:8224, Dagger:8225, bull:8226, hellip:8230, permil:8240, prime:8242, Prime:8243, lsaquo:8249, rsaquo:8250, oline:8254, frasl:8260, euro:8364, image:8465, weierp:8472, real:8476, trade:8482, alefsym:8501, larr:8592, uarr:8593, rarr:8594, darr:8595, harr:8596, crarr:8629, lArr:8656, uArr:8657, rArr:8658, dArr:8659, hArr:8660, forall:8704, part:8706, exist:8707, empty:8709, nabla:8711, isin:8712, notin:8713, ni:8715, prod:8719, sum:8721, minus:8722, lowast:8727, radic:8730, prop:8733, infin:8734, ang:8736, and:8743, or:8744, cap:8745, cup:8746, int:8747, there4:8756, sim:8764, cong:8773, asymp:8776, ne:8800, equiv:8801, le:8804, ge:8805, sub:8834, sup:8835, nsub:8836, sube:8838, supe:8839, oplus:8853, otimes:8855, perp:8869, sdot:8901, lceil:8968, rceil:8969, lfloor:8970, rfloor:8971, lang:9001, rang:9002, loz:9674, spades:9824, clubs:9827, hearts:9829, diams:9830 }; exports.htmlVoidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(","); diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index 10ab90b39..34d11dec7 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -60,7 +60,7 @@ function FramedEngine(options) { this.domNode.value = this.value; } // Set the attributes - if(this.widget.editType) { + if(this.widget.editType && this.widget.editTag !== "textarea") { this.domNode.setAttribute("type",this.widget.editType); } if(this.widget.editPlaceholder) { @@ -118,6 +118,8 @@ FramedEngine.prototype.copyStyles = function() { this.domNode.style.margin = "0"; // In Chrome setting -webkit-text-fill-color overrides the placeholder text colour this.domNode.style["-webkit-text-fill-color"] = "currentcolor"; + // Ensure we don't force text direction to LTR + this.domNode.style.removeProperty("direction"); }; /* @@ -162,13 +164,13 @@ FramedEngine.prototype.fixHeight = function() { if(this.widget.editAutoHeight) { if(this.domNode && !this.domNode.isTiddlyWikiFakeDom) { var newHeight = $tw.utils.resizeTextAreaToFit(this.domNode,this.widget.editMinHeight); - this.iframeNode.style.height = (newHeight + 14) + "px"; // +14 for the border on the textarea + this.iframeNode.style.height = newHeight + "px"; } } else { var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10); fixedHeight = Math.max(fixedHeight,20); this.domNode.style.height = fixedHeight + "px"; - this.iframeNode.style.height = (fixedHeight + 14) + "px"; + this.iframeNode.style.height = fixedHeight + "px"; } } }; @@ -177,9 +179,11 @@ FramedEngine.prototype.fixHeight = function() { Focus the engine node */ FramedEngine.prototype.focus = function() { - if(this.domNode.focus && this.domNode.select) { + if(this.domNode.focus) { this.domNode.focus(); - this.domNode.select(); + } + if(this.domNode.select) { + $tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd); } }; diff --git a/core/modules/editor/engines/simple.js b/core/modules/editor/engines/simple.js index e8be19a75..809dc58ea 100644 --- a/core/modules/editor/engines/simple.js +++ b/core/modules/editor/engines/simple.js @@ -34,7 +34,7 @@ function SimpleEngine(options) { this.domNode.value = this.value; } // Set the attributes - if(this.widget.editType) { + if(this.widget.editType && this.widget.editTag !== "textarea") { this.domNode.setAttribute("type",this.widget.editType); } if(this.widget.editPlaceholder) { @@ -119,10 +119,12 @@ SimpleEngine.prototype.fixHeight = function() { /* Focus the engine node */ -SimpleEngine.prototype.focus = function() { - if(this.domNode.focus && this.domNode.select) { +SimpleEngine.prototype.focus = function() { + if(this.domNode.focus) { this.domNode.focus(); - this.domNode.select(); + } + if(this.domNode.select) { + $tw.utils.setSelectionByPosition(this.domNode,this.widget.editFocusSelectFromStart,this.widget.editFocusSelectFromEnd); } }; diff --git a/core/modules/editor/factory.js b/core/modules/editor/factory.js index 118f44f43..6157ec67f 100644 --- a/core/modules/editor/factory.js +++ b/core/modules/editor/factory.js @@ -180,6 +180,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { this.editMinHeight = this.getAttribute("minHeight",DEFAULT_MIN_TEXT_AREA_HEIGHT); this.editFocusPopup = this.getAttribute("focusPopup"); this.editFocus = this.getAttribute("focus"); + this.editFocusSelectFromStart = $tw.utils.parseNumber(this.getAttribute("focusSelectFromStart","0")); + this.editFocusSelectFromEnd = $tw.utils.parseNumber(this.getAttribute("focusSelectFromEnd","0")); this.editTabIndex = this.getAttribute("tabindex"); this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes"; this.editInputActions = this.getAttribute("inputActions"); @@ -218,7 +220,7 @@ 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 || changedAttributes.fileDrop) { + 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] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) { this.refreshSelf(); return true; } else if (changedTiddlers[this.editRefreshTitle]) { @@ -298,7 +300,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { Propogate keydown events to our container for the keyboard widgets benefit */ EditTextWidget.prototype.propogateKeydownEvent = function(event) { - var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]); + var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]); return !this.parentDomNode.dispatchEvent(newEvent); }; diff --git a/core/modules/filterrunprefixes/cascade.js b/core/modules/filterrunprefixes/cascade.js index da6894d21..486e75f45 100644 --- a/core/modules/filterrunprefixes/cascade.js +++ b/core/modules/filterrunprefixes/cascade.js @@ -25,20 +25,10 @@ exports.cascade = function(operationSubFunction,options) { if(!filterFnList[index]) { filterFnList[index] = options.wiki.compileFilter(filter); } - var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler") - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var output = filterFnList[index](options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler","") + })); if(output.length !== 0) { result = output[0]; return false; diff --git a/core/modules/filterrunprefixes/filter.js b/core/modules/filterrunprefixes/filter.js index 783b699c2..4ab057109 100644 --- a/core/modules/filterrunprefixes/filter.js +++ b/core/modules/filterrunprefixes/filter.js @@ -19,23 +19,13 @@ exports.filter = function(operationSubFunction,options) { var resultsToRemove = [], index = 0; results.each(function(title) { - var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (results.length - 1 - index), - "length": "" + results.length - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler",""), + "index": "" + index, + "revIndex": "" + (results.length - 1 - index), + "length": "" + results.length + })); if(filtered.length === 0) { resultsToRemove.push(title); } diff --git a/core/modules/filterrunprefixes/map.js b/core/modules/filterrunprefixes/map.js index efcb5b534..b756d6699 100644 --- a/core/modules/filterrunprefixes/map.js +++ b/core/modules/filterrunprefixes/map.js @@ -21,23 +21,13 @@ exports.map = function(operationSubFunction,options) { flatten = (suffixes[0] && suffixes[0][0] === "flat") ? true : false; results.clear(); $tw.utils.each(inputTitles,function(title) { - var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (inputTitles.length - 1 - index), - "length": "" + inputTitles.length - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler",""), + "index": "" + index, + "revIndex": "" + (inputTitles.length - 1 - index), + "length": "" + inputTitles.length + })); if(filtered.length && flatten) { $tw.utils.each(filtered,function(value) { results.push(value); diff --git a/core/modules/filterrunprefixes/reduce.js b/core/modules/filterrunprefixes/reduce.js index 8fe819e3f..ee2998837 100644 --- a/core/modules/filterrunprefixes/reduce.js +++ b/core/modules/filterrunprefixes/reduce.js @@ -18,24 +18,14 @@ exports.reduce = function(operationSubFunction,options) { var accumulator = "", index = 0; results.each(function(title) { - var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler"), - "index": "" + index, - "revIndex": "" + (results.length - 1 - index), - "length": "" + results.length, - "accumulator": "" + accumulator - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler"), + "index": "" + index, + "revIndex": "" + (results.length - 1 - index), + "length": "" + results.length, + "accumulator": "" + accumulator + })); if(list.length > 0) { accumulator = "" + list[0]; } diff --git a/core/modules/filterrunprefixes/sort.js b/core/modules/filterrunprefixes/sort.js index 6865b175c..d8d376126 100644 --- a/core/modules/filterrunprefixes/sort.js +++ b/core/modules/filterrunprefixes/sort.js @@ -25,20 +25,10 @@ exports.sort = function(operationSubFunction,options) { indexes = new Array(inputTitles.length), compareFn; results.each(function(title) { - var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ - getVariable: function(name,opts) { - opts = opts || {}; - opts.variables = { - "currentTiddler": "" + title, - "..currentTiddler": widget.getVariable("currentTiddler") - }; - if(name in opts.variables) { - return opts.variables[name]; - } else { - return widget.getVariable(name,opts); - } - } - }); + var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": widget.getVariable("currentTiddler") + })); sortKeys.push(key[0] || ""); }); results.clear(); diff --git a/core/modules/filterrunprefixes/then.js b/core/modules/filterrunprefixes/then.js new file mode 100644 index 000000000..9f6d5c76a --- /dev/null +++ b/core/modules/filterrunprefixes/then.js @@ -0,0 +1,32 @@ +/*\ +title: $:/core/modules/filterrunprefixes/then.js +type: application/javascript +module-type: filterrunprefix + +Replace results of previous runs unless empty + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter prefix function +*/ +exports.then = function(operationSubFunction) { + return function(results,source,widget) { + if(results.length !== 0) { + // Only run if previous run(s) produced results + var thisRunResult = operationSubFunction(source,widget); + if(thisRunResult.length !== 0) { + // Replace results only if this run actually produces a result + results.clear(); + results.pushTop(thisRunResult); + } + } + }; +}; + +})(); diff --git a/core/modules/filters.js b/core/modules/filters.js index 1bb5fe9ff..aa82a352a 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -12,6 +12,8 @@ Adds tiddler filtering methods to the $tw.Wiki object. /*global $tw: false */ "use strict"; +var widgetClass = require("$:/core/modules/widgets/widget.js").widget; + /* Maximum permitted filter recursion depth */ var MAX_FILTER_DEPTH = 300; @@ -255,19 +257,21 @@ exports.compileFilter = function(filterString) { var operands = [], operatorFunction; if(!operator.operator) { + // Use the "title" operator if no operator is specified operatorFunction = filterOperators.title; } else if(!filterOperators[operator.operator]) { - operatorFunction = filterOperators.field; + // Unknown operators treated as "[unknown]" - at run time we can distinguish between a custom operator and falling back to the default "field" operator + operatorFunction = filterOperators["[unknown]"]; } else { + // Use the operator function 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) { var varTree = $tw.utils.parseFilterVariable(operand.text); - operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""}); + operand.value = widgetClass.evaluateVariable(widget,varTree.name,{params: varTree.params, source: source})[0] || ""; } else { operand.value = operand.text; } diff --git a/core/modules/filters/all.js b/core/modules/filters/all.js index a36749e92..3554a74b3 100644 --- a/core/modules/filters/all.js +++ b/core/modules/filters/all.js @@ -28,12 +28,8 @@ function getAllFilterOperators() { Export our filter function */ exports.all = function(source,operator,options) { - // Get our suboperators - var allFilterOperators = getAllFilterOperators(); - // Cycle through the suboperators accumulating their results - var results = new $tw.utils.LinkedList(), - subops = operator.operand.split("+"); // Check for common optimisations + var subops = operator.operand.split("+"); if(subops.length === 1 && subops[0] === "") { return source; } else if(subops.length === 1 && subops[0] === "tiddlers") { @@ -46,6 +42,10 @@ exports.all = function(source,operator,options) { return options.wiki.eachShadowPlusTiddlers; } // Do it the hard way + // Get our suboperators + var allFilterOperators = getAllFilterOperators(); + // Cycle through the suboperators accumulating their results + var results = new $tw.utils.LinkedList(); for(var t=0; t 0) === target) { results.push(title); } diff --git a/core/modules/filters/format/timestamp.js b/core/modules/filters/format/timestamp.js new file mode 100644 index 000000000..d6f5afe30 --- /dev/null +++ b/core/modules/filters/format/timestamp.js @@ -0,0 +1,25 @@ +/*\ +title: $:/core/modules/filters/format/timestamp.js +type: application/javascript +module-type: formatfilteroperator +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.timestamp = function(source,operand,options) { + var results = []; + source(function(tiddler,title) { + if (title.match(/^-?\d+$/)) { + var value = new Date(Number(title)); + results.push($tw.utils.formatDateString(value,operand || "[UTC]YYYY0MM0DD0hh0mm0ss0XXX")); + } + }); + return results; +}; +})(); \ No newline at end of file diff --git a/core/modules/filters/function.js b/core/modules/filters/function.js new file mode 100644 index 000000000..79210fb78 --- /dev/null +++ b/core/modules/filters/function.js @@ -0,0 +1,36 @@ +/*\ +title: $:/core/modules/filters/function.js +type: application/javascript +module-type: filteroperator + +Filter operator returning those input titles that are returned from a function + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.function = function(source,operator,options) { + var functionName = operator.operands[0], + params = []; + $tw.utils.each(operator.operands.slice(1),function(param) { + params.push({value: param}); + }); + var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(functionName,{params: params, source: source}); + if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition) { + return variableInfo.resultList ? variableInfo.resultList : [variableInfo.text]; + } + // Return the input list if the function wasn't found + var results = []; + source(function(tiddler,title) { + results.push(title); + }); + return results; +}; + +})(); diff --git a/core/modules/filters/json-ops.js b/core/modules/filters/json-ops.js index d5e8c33af..0c58964eb 100644 --- a/core/modules/filters/json-ops.js +++ b/core/modules/filters/json-ops.js @@ -17,9 +17,23 @@ exports["jsonget"] = function(source,operator,options) { source(function(tiddler,title) { var data = $tw.utils.parseJSONSafe(title,title); if(data) { - var item = getDataItemValueAsString(data,operator.operands); + var items = getDataItemValueAsStrings(data,operator.operands); + if(items !== undefined) { + results.push.apply(results,items); + } + } + }); + return results; +}; + +exports["jsonextract"] = function(source,operator,options) { + var results = []; + source(function(tiddler,title) { + var data = $tw.utils.parseJSONSafe(title,title); + if(data) { + var item = getDataItem(data,operator.operands); if(item !== undefined) { - results.push(item); + results.push(JSON.stringify(item)); } } }); @@ -31,9 +45,9 @@ exports["jsonindexes"] = function(source,operator,options) { source(function(tiddler,title) { var data = $tw.utils.parseJSONSafe(title,title); if(data) { - var item = getDataItemKeysAsStrings(data,operator.operands); - if(item !== undefined) { - results.push.apply(results,item); + var items = getDataItemKeysAsStrings(data,operator.operands); + if(items !== undefined) { + results.push.apply(results,items); } } }); @@ -54,14 +68,62 @@ exports["jsontype"] = function(source,operator,options) { return results; }; +exports["jsonset"] = function(source,operator,options) { + var suffixes = operator.suffixes || [], + type = suffixes[0] && suffixes[0][0], + indexes = operator.operands.slice(0,-1), + value = operator.operands[operator.operands.length - 1], + results = []; + if(operator.operands.length === 1 && operator.operands[0] === "") { + value = undefined; // Prevents the value from being assigned + } + switch(type) { + case "string": + // Use value unchanged + break; + case "boolean": + value = (value === "true" ? true : (value === "false" ? false : undefined)); + break; + case "number": + value = $tw.utils.parseNumber(value); + break; + case "array": + indexes = operator.operands; + value = []; + break; + case "object": + indexes = operator.operands; + value = {}; + break; + case "null": + indexes = operator.operands; + value = null; + break; + case "json": + value = $tw.utils.parseJSONSafe(value,function() {return undefined;}); + break; + default: + // Use value unchanged + break; + } + source(function(tiddler,title) { + var data = $tw.utils.parseJSONSafe(title,title); + if(data) { + data = setDataItem(data,indexes,value); + results.push(JSON.stringify(data)); + } + }); + return results; +}; + /* Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid */ -function getDataItemValueAsString(data,indexes) { +function getDataItemValueAsStrings(data,indexes) { // Get the item var item = getDataItem(data,indexes); - // Return the item as a string - return convertDataItemValueToString(item); + // Return the item as a string list + return convertDataItemValueToStrings(item); } /* @@ -77,15 +139,34 @@ function getDataItemKeysAsStrings(data,indexes) { /* Return an array of the string representation of the values of a data item, or "undefined" if the item is undefined */ -function convertDataItemValueToString(item) { +function convertDataItemValueToStrings(item) { // Return the item as a string if(item === undefined) { - return item; + return undefined; + } else if(item === null) { + return ["null"] + } else if(typeof item === "object") { + var results = [],i,t; + if($tw.utils.isArray(item)) { + // Return all the items in arrays recursively + for(i=0; i 0) { accumulator = "" + list[0]; } diff --git a/core/modules/filters/sortsub.js b/core/modules/filters/sortsub.js index a926362e3..d328be09c 100644 --- a/core/modules/filters/sortsub.js +++ b/core/modules/filters/sortsub.js @@ -25,18 +25,10 @@ exports.sortsub = function(source,operator,options) { inputTitles.push(title); var r = filterFn.call(options.wiki,function(iterator) { iterator(options.wiki.getTiddler(title),title); - },{ - getVariable: function(name) { - switch(name) { - case "currentTiddler": - return "" + title; - case "..currentTiddler": - return options.widget.getVariable("currentTiddler"); - default: - return options.widget.getVariable(name); - } - } - }); + },options.widget.makeFakeWidgetWithVariables({ + "currentTiddler": "" + title, + "..currentTiddler": options.widget.getVariable("currentTiddler") + })); sortKeys.push(r[0] || ""); }); // Rather than sorting the titles array, we'll sort the indexes so that we can consult both arrays diff --git a/core/modules/filters/strings.js b/core/modules/filters/strings.js index 60a36265d..538dd0597 100644 --- a/core/modules/filters/strings.js +++ b/core/modules/filters/strings.js @@ -74,6 +74,113 @@ exports.join = makeStringReducingOperator( },null ); +var dmp = require("$:/core/modules/utils/diff-match-patch/diff_match_patch.js"); + +exports.levenshtein = makeStringBinaryOperator( + function(a,b) { + var dmpObject = new dmp.diff_match_patch(), + diffs = dmpObject.diff_main(a,b); + return [dmpObject.diff_levenshtein(diffs) + ""]; + } +); + +// these two functions are adapted from https://github.com/google/diff-match-patch/wiki/Line-or-Word-Diffs +function diffLineWordMode(text1,text2,mode) { + var dmpObject = new dmp.diff_match_patch(); + var a = diffPartsToChars(text1,text2,mode); + var lineText1 = a.chars1; + var lineText2 = a.chars2; + var lineArray = a.lineArray; + var diffs = dmpObject.diff_main(lineText1,lineText2,false); + dmpObject.diff_charsToLines_(diffs,lineArray); + return diffs; +} + +function diffPartsToChars(text1,text2,mode) { + var lineArray = []; + var lineHash = {}; + lineArray[0] = ''; + + function diff_linesToPartsMunge_(text,mode) { + var chars = ''; + var lineStart = 0; + var lineEnd = -1; + var lineArrayLength = lineArray.length, + regexpResult; + var searchRegexp = /\W+/g; + while(lineEnd < text.length - 1) { + if(mode === "words") { + regexpResult = searchRegexp.exec(text); + lineEnd = searchRegexp.lastIndex; + if(regexpResult === null) { + lineEnd = text.length; + } + lineEnd = --lineEnd; + } else { + lineEnd = text.indexOf('\n', lineStart); + if(lineEnd == -1) { + lineEnd = text.length - 1; + } + } + var line = text.substring(lineStart, lineEnd + 1); + + if(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : (lineHash[line] !== undefined)) { + chars += String.fromCharCode(lineHash[line]); + } else { + if (lineArrayLength == maxLines) { + line = text.substring(lineStart); + lineEnd = text.length; + } + chars += String.fromCharCode(lineArrayLength); + lineHash[line] = lineArrayLength; + lineArray[lineArrayLength++] = line; + } + lineStart = lineEnd + 1; + } + return chars; + } + var maxLines = 40000; + var chars1 = diff_linesToPartsMunge_(text1,mode); + maxLines = 65535; + var chars2 = diff_linesToPartsMunge_(text2,mode); + return {chars1: chars1, chars2: chars2, lineArray: lineArray}; +}; + +exports.makepatches = function(source,operator,options) { + var dmpObject = new dmp.diff_match_patch(), + suffix = operator.suffix || "", + result = []; + + source(function(tiddler,title) { + var diffs, patches; + if(suffix === "lines" || suffix === "words") { + diffs = diffLineWordMode(title,operator.operand,suffix); + patches = dmpObject.patch_make(title,diffs); + } else { + patches = dmpObject.patch_make(title,operator.operand); + } + Array.prototype.push.apply(result,[dmpObject.patch_toText(patches)]); + }); + + return result; +}; + +exports.applypatches = makeStringBinaryOperator( + function(a,b) { + var dmpObject = new dmp.diff_match_patch(), + patches; + try { + patches = dmpObject.patch_fromText(b); + } catch(e) { + } + if(patches) { + return [dmpObject.patch_apply(patches,a)[0]]; + } else { + return [a]; + } + } +); + function makeStringBinaryOperator(fnCalc) { return function(source,operator,options) { var result = []; @@ -184,4 +291,4 @@ exports.charcode = function(source,operator,options) { return [chars.join("")]; }; -})(); +})(); \ No newline at end of file diff --git a/core/modules/filters/substitute.js b/core/modules/filters/substitute.js new file mode 100644 index 000000000..655ef7321 --- /dev/null +++ b/core/modules/filters/substitute.js @@ -0,0 +1,36 @@ +/*\ +title: $:/core/modules/filters/substitute.js +type: application/javascript +module-type: filteroperator + +Filter operator for substituting variables and embedded filter expressions with their corresponding values + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.substitute = function(source,operator,options) { + var results = [], + operands = []; + $tw.utils.each(operator.operands,function(operand,index){ + operands.push({ + name: (index + 1).toString(), + value: operand + }); + }); + source(function(tiddler,title) { + if(title) { + results.push(options.wiki.getSubstitutedText(title,options.widget,{substitutions:operands})); + } + }); + return results; +}; + +})(); + \ No newline at end of file diff --git a/core/modules/filters/unknown.js b/core/modules/filters/unknown.js new file mode 100644 index 000000000..6ae5baaf0 --- /dev/null +++ b/core/modules/filters/unknown.js @@ -0,0 +1,49 @@ +/*\ +title: $:/core/modules/filters/unknown.js +type: application/javascript +module-type: filteroperator + +Filter operator for handling unknown filter operators. + +Not intended to be used directly by end users, hence the square brackets around the name. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var fieldFilterOperatorFn = require("$:/core/modules/filters/field.js").field; + +/* +Export our filter function +*/ +exports["[unknown]"] = function(source,operator,options) { + // Check for a user defined filter operator + if(operator.operator.indexOf(".") !== -1) { + var params = []; + $tw.utils.each(operator.operands,function(param) { + params.push({value: param}); + }); + var variableInfo = options.widget && options.widget.getVariableInfo && options.widget.getVariableInfo(operator.operator,{params: params, source: source}); + if(variableInfo && variableInfo.srcVariable) { + var list = variableInfo.resultList ? variableInfo.resultList : [variableInfo.text]; + if(operator.prefix === "!") { + var results = []; + source(function(tiddler,title) { + if(list.indexOf(title) === -1) { + results.push(title); + } + }); + return results; + } else { + return list; + } + } + } + // Otherwise, use the "field" operator + return fieldFilterOperatorFn(source,operator,options); +}; + +})(); diff --git a/core/modules/indexers/field-indexer.js b/core/modules/indexers/field-indexer.js index e49583610..3aefc99ac 100644 --- a/core/modules/indexers/field-indexer.js +++ b/core/modules/indexers/field-indexer.js @@ -32,18 +32,18 @@ FieldIndexer.prototype.setMaxIndexedValueLength = function(length) { FieldIndexer.prototype.addIndexMethods = function() { var self = this; + // get all tiddlers, including those overwrite shadow tiddlers this.wiki.each.byField = function(name,value) { - var titles = self.wiki.allTitles(), - lookup = self.lookup(name,value); + var lookup = self.lookup(name,value); return lookup && lookup.filter(function(title) { - return titles.indexOf(title) !== -1; + return self.wiki.tiddlerExists(title) }); }; + // get shadow tiddlers, including shadow tiddlers that is overwritten this.wiki.eachShadow.byField = function(name,value) { - var titles = self.wiki.allShadowTitles(), - lookup = self.lookup(name,value); + var lookup = self.lookup(name,value); return lookup && lookup.filter(function(title) { - return titles.indexOf(title) !== -1; + return self.wiki.isShadowTiddler(title) }); }; this.wiki.eachTiddlerPlusShadows.byField = function(name,value) { diff --git a/core/modules/parsers/audioparser.js b/core/modules/parsers/audioparser.js index 95380bf80..5eb2ff985 100644 --- a/core/modules/parsers/audioparser.js +++ b/core/modules/parsers/audioparser.js @@ -28,6 +28,8 @@ var AudioParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["audio/ogg"] = AudioParser; diff --git a/core/modules/parsers/binaryparser.js b/core/modules/parsers/binaryparser.js index fb3d38678..60e7b5ef0 100644 --- a/core/modules/parsers/binaryparser.js +++ b/core/modules/parsers/binaryparser.js @@ -23,7 +23,7 @@ var BinaryParser = function(type,text,options) { children: [{ type: "transclude", attributes: { - tiddler: {type: "string", value: BINARY_WARNING_MESSAGE} + "$tiddler": {type: "string", value: BINARY_WARNING_MESSAGE} } }] }; @@ -38,7 +38,7 @@ var BinaryParser = function(type,text,options) { children: [{ type: "transclude", attributes: { - tiddler: {type: "string", value: EXPORT_BUTTON_IMAGE} + "$tiddler": {type: "string", value: EXPORT_BUTTON_IMAGE} } }] }; @@ -64,6 +64,8 @@ var BinaryParser = function(type,text,options) { children: [warn, link] } this.tree = [element]; + this.source = text; + this.type = type; }; exports["application/octet-stream"] = BinaryParser; diff --git a/core/modules/parsers/csvparser.js b/core/modules/parsers/csvparser.js index 40431d0ae..f40b5f0e5 100644 --- a/core/modules/parsers/csvparser.js +++ b/core/modules/parsers/csvparser.js @@ -52,6 +52,8 @@ var CsvParser = function(type,text,options) { tag = "td"; this.tree[0].children[0].children[0].children.push(row); } + this.source = text; + this.type = type; }; exports["text/csv"] = CsvParser; diff --git a/core/modules/parsers/htmlparser.js b/core/modules/parsers/htmlparser.js index 206ab9c78..24c9f5d3e 100644 --- a/core/modules/parsers/htmlparser.js +++ b/core/modules/parsers/htmlparser.js @@ -29,6 +29,8 @@ var HtmlParser = function(type,text,options) { if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") { this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")}; } + this.source = text; + this.type = type; }; exports["text/html"] = HtmlParser; diff --git a/core/modules/parsers/imageparser.js b/core/modules/parsers/imageparser.js index e3b8fb60a..a964a4ba8 100644 --- a/core/modules/parsers/imageparser.js +++ b/core/modules/parsers/imageparser.js @@ -28,6 +28,8 @@ var ImageParser = function(type,text,options) { } } this.tree = [element]; + this.source = text; + this.type = type; }; exports["image/svg+xml"] = ImageParser; diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 925674056..1f86dd909 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -123,6 +123,36 @@ exports.parseStringLiteral = function(source,pos) { } }; +/* +Returns an array of {name:} with an optional "default" property. Options include: +requireParenthesis: require the parameter definition to be wrapped in parenthesis +*/ +exports.parseParameterDefinition = function(paramString,options) { + options = options || {}; + if(options.requireParenthesis) { + var parenMatch = /^\s*\((.*)\)\s*$/g.exec(paramString); + if(!parenMatch) { + return []; + } + paramString = parenMatch[1]; + } + var params = [], + reParam = /\s*([^:),\s]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|([^,"'\s]+)))?/mg, + paramMatch = reParam.exec(paramString); + while(paramMatch) { + // Save the parameter details + var paramInfo = {name: paramMatch[1]}, + defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]; + if(defaultValue !== undefined) { + paramInfo["default"] = defaultValue; + } + params.push(paramInfo); + // Look for the next parameter + paramMatch = reParam.exec(paramString); + } + return params; +}; + exports.parseMacroParameters = function(node,source,pos) { // Process parameters var parameter = $tw.utils.parseMacroParameter(source,pos); @@ -175,7 +205,36 @@ exports.parseMacroParameter = function(source,pos) { }; /* -Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:} +Look for a macro invocation. Returns null if not found, or {type: "transclude", attributes:, start:, end:} +*/ +exports.parseMacroInvocationAsTransclusion = function(source,pos) { + var node = $tw.utils.parseMacroInvocation(source,pos); + if(node) { + var positionalName = 0, + transclusion = { + type: "transclude", + start: node.start, + end: node.end + }; + $tw.utils.addAttributeToParseTreeNode(transclusion,"$variable",node.name); + $tw.utils.each(node.params,function(param) { + var name = param.name; + if(name) { + if(name.charAt(0) === "$") { + name = "$" + name; + } + $tw.utils.addAttributeToParseTreeNode(transclusion,{name: name,type: "string", value: param.value, start: param.start, end: param.end}); + } else { + $tw.utils.addAttributeToParseTreeNode(transclusion,{name: (positionalName++) + "",type: "string", value: param.value, start: param.start, end: param.end}); + } + }); + return transclusion; + } + return node; +}; + +/* +Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, params:, start:, end:} */ exports.parseMacroInvocation = function(source,pos) { var node = { @@ -246,10 +305,11 @@ exports.parseAttribute = function(source,pos) { start: pos }; // Define our regexps - var reAttributeName = /([^\/\s>"'=]+)/g, - reUnquotedAttribute = /([^\/\s<>"'=]+)/g, + var reAttributeName = /([^\/\s>"'`=]+)/g, + reUnquotedAttribute = /([^\/\s<>"'`=]+)/g, reFilteredValue = /\{\{\{([\S\s]+?)\}\}\}/g, - reIndirectValue = /\{\{([^\}]+)\}\}/g; + reIndirectValue = /\{\{([^\}]+)\}\}/g, + reSubstitutedValue = /(?:```([\s\S]*?)```|`([^`]|[\S\s]*?)`)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Get the attribute name @@ -302,8 +362,15 @@ exports.parseAttribute = function(source,pos) { node.type = "macro"; node.value = macroInvocation; } else { - node.type = "string"; - node.value = "true"; + var substitutedValue = $tw.utils.parseTokenRegExp(source,pos,reSubstitutedValue); + if(substitutedValue) { + pos = substitutedValue.end; + node.type = "substituted"; + node.rawValue = substitutedValue.match[1] || substitutedValue.match[2]; + } else { + node.type = "string"; + node.value = "true"; + } } } } diff --git a/core/modules/parsers/pdfparser.js b/core/modules/parsers/pdfparser.js index 95d74ef4b..c7830bf69 100644 --- a/core/modules/parsers/pdfparser.js +++ b/core/modules/parsers/pdfparser.js @@ -15,7 +15,7 @@ The PDF parser embeds a PDF viewer var ImageParser = function(type,text,options) { var element = { type: "element", - tag: "embed", + tag: "iframe", attributes: {} }, src; @@ -25,6 +25,8 @@ var ImageParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:application/pdf;base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["application/pdf"] = ImageParser; diff --git a/core/modules/parsers/textparser.js b/core/modules/parsers/textparser.js index 4f55f6f0c..17f9bde10 100644 --- a/core/modules/parsers/textparser.js +++ b/core/modules/parsers/textparser.js @@ -14,12 +14,16 @@ The plain text parser processes blocks of source text into a degenerate parse tr var TextParser = function(type,text,options) { this.tree = [{ - type: "codeblock", + type: "genesis", attributes: { - code: {type: "string", value: text}, - language: {type: "string", value: type} + $type: {name: "$type", type: "string", value: "$codeblock"}, + code: {name: "code", type: "string", value: text}, + language: {name: "language", type: "string", value: type}, + $remappable: {name: "$remappable", type:"string", value: "no"} } }]; + this.source = text; + this.type = type; }; exports["text/plain"] = TextParser; @@ -30,4 +34,3 @@ exports["text/css"] = TextParser; exports["application/x-tiddler-dictionary"] = TextParser; })(); - diff --git a/core/modules/parsers/videoparser.js b/core/modules/parsers/videoparser.js index f1c281c7c..1c8a38bb2 100644 --- a/core/modules/parsers/videoparser.js +++ b/core/modules/parsers/videoparser.js @@ -28,6 +28,8 @@ var VideoParser = function(type,text,options) { element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text}; } this.tree = [element]; + this.source = text; + this.type = type; }; exports["video/ogg"] = VideoParser; diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js new file mode 100644 index 000000000..23940fd88 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -0,0 +1,120 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/conditional.js +type: application/javascript +module-type: wikirule + +Conditional shortcut syntax + +``` +This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %> +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "conditional"; +exports.types = {inline: true, block: true}; + +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /\<\%\s*if\s+/mg; + this.terminateIfRegExp = /\%\>/mg; +}; + +exports.findNextMatch = function(startPos) { + // Look for the next <% if shortcut + this.matchRegExp.lastIndex = startPos; + this.match = this.matchRegExp.exec(this.parser.source); + // If not found then return no match + if(!this.match) { + return undefined; + } + // Check for the next %> + this.terminateIfRegExp.lastIndex = this.match.index; + this.terminateIfMatch = this.terminateIfRegExp.exec(this.parser.source); + // If not found then return no match + if(!this.terminateIfMatch) { + return undefined; + } + // Return the position at which the construction was found + return this.match.index; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Get the filter condition + var filterCondition = this.parser.source.substring(this.match.index + this.match[0].length,this.terminateIfMatch.index); + // Advance the parser position to past the %> + this.parser.pos = this.terminateIfMatch.index + this.terminateIfMatch[0].length; + // Parse the if clause + return this.parseIfClause(filterCondition); +}; + +exports.parseIfClause = function(filterCondition) { + // Create the list widget + var listWidget = { + type: "list", + tag: "$list", + isBlock: this.is.block, + children: [ + { + type: "list-template", + tag: "$list-template" + }, + { + type: "list-empty", + tag: "$list-empty" + } + ] + }; + $tw.utils.addAttributeToParseTreeNode(listWidget,"filter",filterCondition); + $tw.utils.addAttributeToParseTreeNode(listWidget,"variable","condition"); + $tw.utils.addAttributeToParseTreeNode(listWidget,"limit","1"); + // Check for an immediately following double linebreak + var hasLineBreak = !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g); + // Parse the body looking for else or endif + var reEndString = "\\<\\%\\s*(endif)\\s*\\%\\>|\\<\\%\\s*(else)\\s*\\%\\>|\\<\\%\\s*(elseif)\\s+([\\s\\S]+?)\\%\\>", + ex; + if(hasLineBreak) { + ex = this.parser.parseBlocksTerminatedExtended(reEndString); + } else { + var reEnd = new RegExp(reEndString,"mg"); + ex = this.parser.parseInlineRunTerminatedExtended(reEnd,{eatTerminator: true}); + } + // Put the body into the list template + listWidget.children[0].children = ex.tree; + // Check for an else or elseif + if(ex.match) { + if(ex.match[1] === "endif") { + // Nothing to do if we just found an endif + } else if(ex.match[2] === "else") { + // Check for an immediately following double linebreak + hasLineBreak = !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n\r]*\r?\n(?:[^\S\n\r]*\r?\n|$))/g); + // If we found an else then we need to parse the body looking for the endif + var reEndString = "\\<\\%\\s*(endif)\\s*\\%\\>", + ex; + if(hasLineBreak) { + ex = this.parser.parseBlocksTerminatedExtended(reEndString); + } else { + var reEnd = new RegExp(reEndString,"mg"); + ex = this.parser.parseInlineRunTerminatedExtended(reEnd,{eatTerminator: true}); + } + // Put the parsed content inside the list empty template + listWidget.children[1].children = ex.tree; + } else if(ex.match[3] === "elseif") { + // Parse the elseif clause by reusing this parser, passing the new filter condition + listWidget.children[1].children = this.parseIfClause(ex.match[4]); + } + } + // Return the parse tree node + return [listWidget]; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js new file mode 100644 index 000000000..85bd14d5c --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -0,0 +1,97 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/fnprocdef.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for function, procedure and widget definitions + +``` +\function name(param:defaultvalue,param2:defaultvalue) +definition text +\end + +\procedure name(param:defaultvalue,param2:defaultvalue) +definition text +\end + +\widget $mywidget(param:defaultvalue,param2:defaultvalue) +definition text +\end +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "fnprocdef"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /\\(function|procedure|widget)\s+([^(\s]+)\((\s*([^)]*))?\)(\s*\r?\n)?/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Move past the macro name and parameters + this.parser.pos = this.matchRegExp.lastIndex; + // Parse the parameters + var params = []; + if(this.match[3]) { + params = $tw.utils.parseParameterDefinition(this.match[4]); + } + // Is the remainder of the line blank after the parameter close paren? + var reEnd; + if(this.match[5]) { + // If so, it is a multiline definition and the end of the body is marked with \end + reEnd = new RegExp("((:?^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[2]) + ")?(?:$|\\r?\\n))","mg"); + } else { + // Otherwise, the end of the definition is marked by the end of the line + reEnd = /($|\r?\n)/mg; + // Move past any whitespace + this.parser.pos = $tw.utils.skipWhiteSpace(this.parser.source,this.parser.pos); + } + // Find the end of the definition + reEnd.lastIndex = this.parser.pos; + var text, + endMatch = reEnd.exec(this.parser.source); + if(endMatch) { + text = this.parser.source.substring(this.parser.pos,endMatch.index); + this.parser.pos = endMatch.index + endMatch[0].length; + } else { + // We didn't find the end of the definition, so we'll make it blank + text = ""; + } + // Save the macro definition + var parseTreeNodes = [{ + type: "set", + attributes: {}, + children: [], + params: params + }]; + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[2]); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); + if(this.match[1] === "function") { + parseTreeNodes[0].isFunctionDefinition = true; + } else if(this.match[1] === "procedure") { + parseTreeNodes[0].isProcedureDefinition = true; + } else if(this.match[1] === "widget") { + parseTreeNodes[0].isWidgetDefinition = true; + } + if(this.parser.configTrimWhiteSpace) { + parseTreeNodes[0].configTrimWhiteSpace = true; + } + return parseTreeNodes; +}; + +})(); + \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 7fc4bb96e..4dbd6a07c 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -78,7 +78,7 @@ exports.parseTag = function(source,pos,options) { orderedAttributes: [] }; // Define our regexps - var reTagName = /([a-zA-Z0-9\-\$]+)/g; + var reTagName = /([a-zA-Z0-9\-\$\.]+)/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); // Look for a less than sign @@ -93,9 +93,6 @@ exports.parseTag = function(source,pos,options) { return null; } node.tag = token.match[1]; - if(node.tag.slice(1).indexOf("$") !== -1) { - return null; - } if(node.tag.charAt(0) === "$") { node.type = node.tag.substr(1); } @@ -141,7 +138,7 @@ exports.parseTag = function(source,pos,options) { exports.findNextTag = function(source,pos,options) { // A regexp for finding candidate HTML tags - var reLookahead = /<([a-zA-Z\-\$]+)/g; + var reLookahead = /<([a-zA-Z\-\$\.]+)/g; // Find the next candidate reLookahead.lastIndex = pos; var match = reLookahead.exec(source); diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index 9556c7af5..a66df7057 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -25,7 +25,7 @@ Instantiate parse rule exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /^\\import[^\S\n]/mg; + this.matchRegExp = /\\import[^\S\n]/mg; }; /* diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index 6f50fdbb0..a2c10e04a 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) { var nextStart = startPos; // Try parsing at all possible macrocall openers until we match while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) { - var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart); + var nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart); if(nextCall) { var c = this.parser.source.charAt(nextCall.end); // Ensure EOL after parsed macro diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index 165a70dce..e9f79f09e 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -27,7 +27,7 @@ exports.findNextMatch = function(startPos) { var nextStart = startPos; // Try parsing at all possible macrocall openers until we match while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) { - this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart); + this.nextCall = $tw.utils.parseMacroInvocationAsTransclusion(this.parser.source,nextStart); if(this.nextCall) { return nextStart; } diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 22a7b5ba7..2001f70d5 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -27,7 +27,7 @@ Instantiate parse rule exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /^\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg; + this.matchRegExp = /\\define\s+([^(\s]+)\(\s*([^)]*)\)(\s*\r?\n)?/mg; }; /* @@ -54,11 +54,11 @@ exports.parse = function() { paramMatch = reParam.exec(paramString); } } - // Is this a multiline definition? + // Is the remainder of the \define line blank after the parameter close paren? var reEnd; if(this.match[3]) { - // If so, the end of the body is marked with \end - reEnd = new RegExp("(\\r?\\n\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); + // If so, it is a multiline definition and the end of the body is marked with \end + reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line reEnd = /($|\r?\n)/mg; @@ -77,16 +77,16 @@ exports.parse = function() { text = ""; } // Save the macro definition - return [{ + var parseTreeNodes = [{ type: "set", - attributes: { - name: {type: "string", value: this.match[1]}, - value: {type: "string", value: text} - }, + attributes: {}, children: [], params: params, isMacroDefinition: true }]; + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); + return parseTreeNodes; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js new file mode 100644 index 000000000..60bbd8901 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -0,0 +1,60 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/parameters.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for parameter definitions + +``` +\parameters(param:defaultvalue,param2:defaultvalue) +definition text +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "parameters"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /\\parameters\s*\(([^)]*)\)(\s*\r?\n)?/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Move past the macro name and parameters + this.parser.pos = this.matchRegExp.lastIndex; + // Parse the parameters + var params = $tw.utils.parseParameterDefinition(this.match[1]); + var attributes = Object.create(null), + orderedAttributes = []; + $tw.utils.each(params,function(param) { + var name = param.name; + // Parameter names starting with dollar must be escaped to double dollars for the parameters widget + if(name.charAt(0) === "$") { + name = "$" + name; + } + var attribute = {name: name, type: "string", value: param["default"] || ""}; + attributes[name] = attribute; + orderedAttributes.push(attribute); + }); + // Save the macro definition + return [{ + type: "parameters", + attributes: attributes, + orderedAttributes: orderedAttributes + }]; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js new file mode 100644 index 000000000..72a6de067 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -0,0 +1,68 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/parsermode.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for parser mode specifications + +``` +\parsermode block +\parsermode inline +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "parsermode"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /\\parsermode[^\S\n]/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Move past the pragma invocation + this.parser.pos = this.matchRegExp.lastIndex; + // Parse whitespace delimited tokens terminated by a line break + var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg, + parserMode = undefined; + reMatch.lastIndex = this.parser.pos; + var match = reMatch.exec(this.parser.source); + while(match && match.index === this.parser.pos) { + this.parser.pos = reMatch.lastIndex; + // Exit if we've got the line break + if(match[2]) { + break; + } + // Process the token + if(match[1]) { + parserMode = match[1]; + } + // Match the next token + match = reMatch.exec(this.parser.source); + } + // Process the tokens + if(parserMode !== undefined) { + if(parserMode === "block") { + this.parser.parseAsInline = false; + } else if(parserMode === "inline") { + this.parser.parseAsInline = true; + } + } + // No parse tree nodes to return + return []; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/rules/rules.js b/core/modules/parsers/wikiparser/rules/rules.js index cfc03330b..1d0f80f29 100644 --- a/core/modules/parsers/wikiparser/rules/rules.js +++ b/core/modules/parsers/wikiparser/rules/rules.js @@ -26,7 +26,7 @@ Instantiate parse rule exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /^\\rules[^\S\n]/mg; + this.matchRegExp = /\\rules[^\S\n]/mg; }; /* diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 56a4f63b8..c033c2440 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -23,7 +23,7 @@ exports.types = {block: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}(?:\r?\n|$)/mg; + this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}(?:\r?\n|$)/mg; }; exports.parse = function() { @@ -31,13 +31,22 @@ exports.parse = function() { this.parser.pos = this.matchRegExp.lastIndex; // Get the match details var template = $tw.utils.trim(this.match[2]), - textRef = $tw.utils.trim(this.match[1]); + textRef = $tw.utils.trim(this.match[1]), + params = this.match[3] ? this.match[3].split("|") : []; // Prepare the transclude widget var transcludeNode = { type: "transclude", attributes: {}, isBlock: true }; + $tw.utils.each(params,function(paramValue,index) { + var name = "" + index; + transcludeNode.attributes[name] = { + name: name, + type: "string", + value: paramValue + } + }); // Prepare the tiddler widget var tr, targetTitle, targetField, targetIndex, tiddlerNode; if(textRef) { @@ -48,14 +57,14 @@ exports.parse = function() { tiddlerNode = { type: "tiddler", attributes: { - tiddler: {type: "string", value: targetTitle} + tiddler: {name: "tiddler", type: "string", value: targetTitle} }, isBlock: true, children: [transcludeNode] }; } if(template) { - transcludeNode.attributes.tiddler = {type: "string", value: template}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template}; if(textRef) { return [tiddlerNode]; } else { @@ -63,12 +72,12 @@ exports.parse = function() { } } else { if(textRef) { - transcludeNode.attributes.tiddler = {type: "string", value: targetTitle}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle}; if(targetField) { - transcludeNode.attributes.field = {type: "string", value: targetField}; + transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField}; } if(targetIndex) { - transcludeNode.attributes.index = {type: "string", value: targetIndex}; + transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex}; } return [tiddlerNode]; } else { diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index dbf39bfb6..3ce9dc78e 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -23,7 +23,7 @@ exports.types = {inline: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?\}\}/mg; + this.matchRegExp = /\{\{([^\{\}\|]*)(?:\|\|([^\|\{\}]+))?(?:\|([^\{\}]+))?\}\}/mg; }; exports.parse = function() { @@ -31,12 +31,21 @@ exports.parse = function() { this.parser.pos = this.matchRegExp.lastIndex; // Get the match details var template = $tw.utils.trim(this.match[2]), - textRef = $tw.utils.trim(this.match[1]); + textRef = $tw.utils.trim(this.match[1]), + params = this.match[3] ? this.match[3].split("|") : []; // Prepare the transclude widget var transcludeNode = { type: "transclude", attributes: {} }; + $tw.utils.each(params,function(paramValue,index) { + var name = "" + index; + transcludeNode.attributes[name] = { + name: name, + type: "string", + value: paramValue + } + }); // Prepare the tiddler widget var tr, targetTitle, targetField, targetIndex, tiddlerNode; if(textRef) { @@ -47,13 +56,13 @@ exports.parse = function() { tiddlerNode = { type: "tiddler", attributes: { - tiddler: {type: "string", value: targetTitle} + tiddler: {name: "tiddler", type: "string", value: targetTitle} }, children: [transcludeNode] }; } if(template) { - transcludeNode.attributes.tiddler = {type: "string", value: template}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: template}; if(textRef) { return [tiddlerNode]; } else { @@ -61,12 +70,12 @@ exports.parse = function() { } } else { if(textRef) { - transcludeNode.attributes.tiddler = {type: "string", value: targetTitle}; + transcludeNode.attributes["$tiddler"] = {name: "$tiddler", type: "string", value: targetTitle}; if(targetField) { - transcludeNode.attributes.field = {type: "string", value: targetField}; + transcludeNode.attributes["$field"] = {name: "$field", type: "string", value: targetField}; } if(targetIndex) { - transcludeNode.attributes.index = {type: "string", value: targetIndex}; + transcludeNode.attributes["$index"] = {name: "$index", type: "string", value: targetIndex}; } return [tiddlerNode]; } else { diff --git a/core/modules/parsers/wikiparser/rules/whitespace.js b/core/modules/parsers/wikiparser/rules/whitespace.js index e3b0c8e3f..5fd9d4b83 100644 --- a/core/modules/parsers/wikiparser/rules/whitespace.js +++ b/core/modules/parsers/wikiparser/rules/whitespace.js @@ -26,7 +26,7 @@ Instantiate parse rule exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /^\\whitespace[^\S\n]/mg; + this.matchRegExp = /\\whitespace[^\S\n]/mg; }; /* diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js new file mode 100644 index 000000000..60cb3d992 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -0,0 +1,40 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +type: application/javascript +module-type: wikirule + +Wiki text inline rule for suppressed wiki links. For example: + +``` +~SuppressedLink +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "wikilinkprefix"; +exports.types = {inline: true}; + +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = new RegExp($tw.config.textPrimitives.unWikiLink + $tw.config.textPrimitives.wikiLink,"mg"); +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + // Get the details of the match + var linkText = this.match[0]; + // Move past the wikilink + this.parser.pos = this.matchRegExp.lastIndex; + // Return the link without unwikilink character as plain text + return [{type: "text", text: linkText.substr(1)}]; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index ff6c1df54..45c4708a2 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -32,6 +32,7 @@ options: see below: parseAsInline: true to parse text as inline instead of block wiki: reference to wiki to use _canonical_uri: optional URI of content if text is missing or empty + configTrimWhiteSpace: true to trim whitespace */ var WikiParser = function(type,text,options) { this.wiki = options.wiki; @@ -46,7 +47,9 @@ var WikiParser = function(type,text,options) { this.source = text || ""; this.sourceLength = this.source.length; // Flag for ignoring whitespace - this.configTrimWhiteSpace = false; + this.configTrimWhiteSpace = options.configTrimWhiteSpace !== undefined ? options.configTrimWhiteSpace : false; + // Parser mode + this.parseAsInline = options.parseAsInline; // Set current parse position this.pos = 0; // Start with empty output @@ -83,7 +86,7 @@ var WikiParser = function(type,text,options) { // Parse any pragmas var topBranch = this.parsePragmas(); // Parse the text into inline runs or blocks - if(options.parseAsInline) { + if(this.parseAsInline) { topBranch.push.apply(topBranch,this.parseInlineRun()); } else { topBranch.push.apply(topBranch,this.parseBlocks()); @@ -191,6 +194,7 @@ Parse any pragmas at the beginning of a block of parse text WikiParser.prototype.parsePragmas = function() { var currentTreeBranch = this.tree; while(true) { + var savedPos = this.pos; // Skip whitespace this.skipWhitespace(); // Check for the end of the text @@ -201,6 +205,7 @@ WikiParser.prototype.parsePragmas = function() { var nextMatch = this.findNextMatch(this.pragmaRules,this.pos); // If not, just exit if(!nextMatch || nextMatch.matchIndex !== this.pos) { + this.pos = savedPos; break; } // Process the pragma rule @@ -211,6 +216,8 @@ WikiParser.prototype.parsePragmas = function() { subTree[0].children = []; currentTreeBranch = subTree[0].children; } + // Skip whitespace after the pragma + this.skipWhitespace(); } return currentTreeBranch; }; @@ -220,7 +227,7 @@ Parse a block from the current position terminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis */ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { - var terminatorRegExp = terminatorRegExpString ? new RegExp("(" + terminatorRegExpString + "|\\r?\\n\\r?\\n)","mg") : /(\r?\n\r?\n)/mg; + var terminatorRegExp = terminatorRegExpString ? new RegExp(terminatorRegExpString + "|\\r?\\n\\r?\\n","mg") : /(\r?\n\r?\n)/mg; this.skipWhitespace(); if(this.pos >= this.sourceLength) { return []; @@ -234,9 +241,10 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { var start = this.pos; var children = this.parseInlineRun(terminatorRegExp); var end = this.pos; + // return [{type: "element", tag: "p", children: children, start: start, end: end }]; if (children[0].type === "text" || (($tw.config.htmlBlockElements.indexOf(children[0].tag) === -1) && children[0] && - children[0].tag && children[0].tag.charAt(0) !== "$")) { + children[0].tag && children[0].tag.charAt(0) !== "$")) { return [{type: "element", tag: "p", children: children, start: start, end: end }]; } else { return children; @@ -267,11 +275,21 @@ WikiParser.prototype.parseBlocksUnterminated = function() { }; /* -Parse blocks of text until a terminating regexp is encountered +Parse blocks of text until a terminating regexp is encountered. Wrapper for parseBlocksTerminatedExtended that just returns the parse tree */ WikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) { - var terminatorRegExp = new RegExp("(" + terminatorRegExpString + ")","mg"), - tree = []; + var ex = this.parseBlocksTerminatedExtended(terminatorRegExpString); + return ex.tree; +}; + +/* +Parse blocks of text until a terminating regexp is encountered +*/ +WikiParser.prototype.parseBlocksTerminatedExtended = function(terminatorRegExpString) { + var terminatorRegExp = new RegExp(terminatorRegExpString,"mg"), + result = { + tree: [] + }; // Skip any whitespace this.skipWhitespace(); // Check if we've got the end marker @@ -280,7 +298,7 @@ WikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) { // Parse the text into blocks while(this.pos < this.sourceLength && !(match && match.index === this.pos)) { var blocks = this.parseBlock(terminatorRegExpString); - tree.push.apply(tree,blocks); + result.tree.push.apply(result.tree,blocks); // Skip any whitespace this.skipWhitespace(); // Check if we've got the end marker @@ -289,8 +307,9 @@ WikiParser.prototype.parseBlocksTerminated = function(terminatorRegExpString) { } if(match && match.index === this.pos) { this.pos = match.index + match[0].length; + result.match = match; } - return tree; + return result; }; /* @@ -333,6 +352,11 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) { }; WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,options) { + var ex = this.parseInlineRunTerminatedExtended(terminatorRegExp,options); + return ex.tree; +}; + +WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegExp,options) { options = options || {}; var tree = []; // Find the next occurrence of the terminator @@ -352,7 +376,10 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option if(options.eatTerminator) { this.pos += terminatorMatch[0].length; } - return tree; + return { + match: terminatorMatch, + tree: tree + }; } } // Process any inline rule, along with the text preceding it @@ -376,7 +403,9 @@ WikiParser.prototype.parseInlineRunTerminated = function(terminatorRegExp,option this.pushTextWidget(tree,this.source.substr(this.pos),this.pos,this.sourceLength); } this.pos = this.sourceLength; - return tree; + return { + tree: tree + }; }; /* diff --git a/core/modules/savers/beaker.js b/core/modules/savers/beaker.js deleted file mode 100644 index dc24ef67f..000000000 --- a/core/modules/savers/beaker.js +++ /dev/null @@ -1,64 +0,0 @@ -/*\ -title: $:/core/modules/savers/beaker.js -type: application/javascript -module-type: saver - -Saves files using the Beaker browser's (https://beakerbrowser.com) Dat protocol (https://datproject.org/) -Compatible with beaker >= V0.7.2 - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -/* -Set up the saver -*/ -var BeakerSaver = function(wiki) { - this.wiki = wiki; -}; - -BeakerSaver.prototype.save = function(text,method,callback) { - var dat = new DatArchive("" + 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("Beaker Saver Write Error: " + reason); - }); - },function(reason) { - callback("Beaker Saver Stat Error: " + reason); - }); - return true; -}; - -/* -Information about this saver -*/ -BeakerSaver.prototype.info = { - name: "beaker", - priority: 3000, - capabilities: ["save", "autosave"] -}; - -/* -Static method that returns true if this saver is capable of working -*/ -exports.canSave = function(wiki) { - return !!window.DatArchive && location.protocol==="dat:"; -}; - -/* -Create an instance of this saver -*/ -exports.create = function(wiki) { - return new BeakerSaver(wiki); -}; - -})(); diff --git a/core/modules/savers/github.js b/core/modules/savers/github.js index f9b87263d..c0a34f2d6 100644 --- a/core/modules/savers/github.js +++ b/core/modules/savers/github.js @@ -31,7 +31,7 @@ GitHubSaver.prototype.save = function(text,method,callback) { headers = { "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json;charset=UTF-8", - "Authorization": "Basic " + window.btoa(username + ":" + password), + "Authorization": "Basic " + $tw.utils.base64Encode(username + ":" + password), "If-None-Match": "" }; // Bail if we don't have everything we need diff --git a/core/modules/savers/hyperdrive.js b/core/modules/savers/hyperdrive.js deleted file mode 100644 index 232392672..000000000 --- a/core/modules/savers/hyperdrive.js +++ /dev/null @@ -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); -}; - -})(); diff --git a/core/modules/server/authenticators/header.js b/core/modules/server/authenticators/header.js index 78ae6cb0a..9d9990d31 100644 --- a/core/modules/server/authenticators/header.js +++ b/core/modules/server/authenticators/header.js @@ -37,7 +37,7 @@ HeaderAuthenticator.prototype.authenticateRequest = function(request,response,st return false; } else { // authenticatedUsername will be undefined for anonymous users - state.authenticatedUsername = username; + state.authenticatedUsername = $tw.utils.decodeURIComponentSafe(username); return true; } }; diff --git a/core/modules/server/routes/get-status.js b/core/modules/server/routes/get-status.js index dd4c1909a..ac35ee874 100644 --- a/core/modules/server/routes/get-status.js +++ b/core/modules/server/routes/get-status.js @@ -21,6 +21,7 @@ exports.handler = function(request,response,state) { username: state.authenticatedUsername || state.server.get("anon-username") || "", anonymous: !state.authenticatedUsername, read_only: !state.server.isAuthorized("writers",state.authenticatedUsername), + logout_is_available: false, space: { recipe: "default" }, diff --git a/core/modules/startup/plugins.js b/core/modules/startup/plugins.js index cad61b104..ab74214b9 100644 --- a/core/modules/startup/plugins.js +++ b/core/modules/startup/plugins.js @@ -15,6 +15,7 @@ Startup logic concerned with managing plugins // Export name and synchronous status exports.name = "plugins"; exports.after = ["load-modules"]; +exports.before = ["startup"]; exports.synchronous = true; var TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE = "$:/status/RequireReloadDueToPluginChange"; diff --git a/core/modules/startup/rootwidget.js b/core/modules/startup/rootwidget.js index 41f3fe03f..716275cda 100644 --- a/core/modules/startup/rootwidget.js +++ b/core/modules/startup/rootwidget.js @@ -20,6 +20,39 @@ exports.before = ["story"]; exports.synchronous = true; exports.startup = function() { + // Install the HTTP client event handler + $tw.httpClient = new $tw.utils.HttpClient(); + var getPropertiesWithPrefix = function(properties,prefix) { + var result = Object.create(null); + $tw.utils.each(properties,function(value,name) { + if(name.indexOf(prefix) === 0) { + result[name.substring(prefix.length)] = properties[name]; + } + }); + return result; + }; + $tw.rootWidget.addEventListener("tm-http-request",function(event) { + var params = event.paramObject || {}; + $tw.httpClient.initiateHttpRequest({ + wiki: event.widget.wiki, + url: params.url, + method: params.method, + body: params.body, + binary: params.binary, + oncompletion: params.oncompletion, + onprogress: params.onprogress, + bindStatus: params["bind-status"], + bindProgress: params["bind-progress"], + variables: getPropertiesWithPrefix(params,"var-"), + headers: getPropertiesWithPrefix(params,"header-"), + passwordHeaders: getPropertiesWithPrefix(params,"password-header-"), + queryStrings: getPropertiesWithPrefix(params,"query-"), + passwordQueryStrings: getPropertiesWithPrefix(params,"password-query-") + }); + }); + $tw.rootWidget.addEventListener("tm-http-cancel-all-requests",function(event) { + $tw.httpClient.cancelAllHttpRequests(); + }); // Install the modal message mechanism $tw.modal = new $tw.utils.Modal($tw.wiki); $tw.rootWidget.addEventListener("tm-modal",function(event) { @@ -41,12 +74,8 @@ exports.startup = function() { $tw.rootWidget.addEventListener("tm-focus-selector",function(event) { var selector = event.param || "", element, - doc = event.event && event.event.target ? event.event.target.ownerDocument : document; - try { - element = doc.querySelector(selector); - } catch(e) { - console.log("Error in selector: ",selector) - } + baseElement = event.event && event.event.target ? event.event.target.ownerDocument : document; + element = $tw.utils.querySelectorSafe(selector,baseElement); if(element && element.focus) { element.focus(event.paramObject); } @@ -87,13 +116,6 @@ exports.startup = function() { } }); } - // If we're being viewed on a data: URI then give instructions for how to save - if(document.location.protocol === "data:") { - $tw.rootWidget.dispatchEvent({ - type: "tm-modal", - param: "$:/language/Modals/SaveInstructions" - }); - } }; })(); diff --git a/core/modules/startup/startup.js b/core/modules/startup/startup.js index e0990228f..e09f6393f 100755 --- a/core/modules/startup/startup.js +++ b/core/modules/startup/startup.js @@ -27,6 +27,11 @@ exports.startup = function() { if($tw.browser) { $tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent)); $tw.browser.isFirefox = !!document.mozFullScreenEnabled; + // 2023-07-21 Edge returns UA below. So we use "isChromeLike" + //'mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/114.0.0.0 safari/537.36 edg/114.0.1823.82' + $tw.browser.isChromeLike = navigator.userAgent.toLowerCase().indexOf("chrome") > -1; + $tw.browser.hasTouch = !!window.matchMedia && window.matchMedia("(pointer: coarse)").matches; + $tw.browser.isMobileChrome = $tw.browser.isChromeLike && $tw.browser.hasTouch; } // Platform detection $tw.platform = {}; diff --git a/core/modules/startup/windows.js b/core/modules/startup/windows.js index 384961b7b..aa9f982ed 100644 --- a/core/modules/startup/windows.js +++ b/core/modules/startup/windows.js @@ -40,7 +40,7 @@ exports.startup = function() { variables = $tw.utils.extend({},paramObject,{currentTiddler: title, "tv-window-id": windowID}); // Open the window var srcWindow, - srcDocument; + srcDocument; // In case that popup blockers deny opening a new window try { srcWindow = window.open("","external-" + windowID,"scrollbars,width=" + width + ",height=" + height + (top ? ",top=" + top : "" ) + (left ? ",left=" + left : "" )), @@ -52,6 +52,7 @@ exports.startup = function() { $tw.windows[windowID] = srcWindow; // Check for reopening the same window if(srcWindow.haveInitialisedWindow) { + srcWindow.focus(); return; } // Initialise the document diff --git a/core/modules/storyviews/zoomin.js b/core/modules/storyviews/zoomin.js index b2796e953..d02f705e7 100644 --- a/core/modules/storyviews/zoomin.js +++ b/core/modules/storyviews/zoomin.js @@ -17,6 +17,10 @@ var easing = "cubic-bezier(0.645, 0.045, 0.355, 1)"; // From http://easings.net/ var ZoominListView = function(listWidget) { var self = this; this.listWidget = listWidget; + this.textNodeLogger = new $tw.utils.Logger("zoomin story river view", { + enable: true, + colour: 'red' + }); // Get the index of the tiddler that is at the top of the history var history = this.listWidget.wiki.getTiddlerDataCached(this.listWidget.historyTitle,[]), targetTiddler; @@ -48,7 +52,10 @@ ZoominListView.prototype.navigateTo = function(historyInfo) { var listItemWidget = this.listWidget.children[listElementIndex], targetElement = listItemWidget.findFirstDomNode(); // Abandon if the list entry isn't a DOM element (it might be a text node) - if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) { + if(!targetElement) { + return; + } else if (targetElement.nodeType === Node.TEXT_NODE) { + this.logTextNodeRoot(targetElement); return; } // Make the new tiddler be position absolute and visible so that we can measure it @@ -122,7 +129,7 @@ function findTitleDomNode(widget,targetClass) { targetClass = targetClass || "tc-title"; var domNode = widget.findFirstDomNode(); if(domNode && domNode.querySelector) { - return domNode.querySelector("." + targetClass); + return $tw.utils.querySelectorSafe("." + targetClass,domNode); } return null; } @@ -130,7 +137,10 @@ function findTitleDomNode(widget,targetClass) { ZoominListView.prototype.insert = function(widget) { var targetElement = widget.findFirstDomNode(); // Abandon if the list entry isn't a DOM element (it might be a text node) - if(!targetElement || targetElement.nodeType === Node.TEXT_NODE) { + if(!targetElement) { + return; + } else if (targetElement.nodeType === Node.TEXT_NODE) { + this.logTextNodeRoot(targetElement); return; } // Make the newly inserted node position absolute and hidden @@ -173,16 +183,21 @@ ZoominListView.prototype.remove = function(widget) { var toWidgetDomNode = toWidget && toWidget.findFirstDomNode(); // Set up the tiddler we're moving back in if(toWidgetDomNode) { - $tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler"); - $tw.utils.setStyle(toWidgetDomNode,[ - {display: "block"}, - {transformOrigin: "50% 50%"}, - {transform: "translateX(0px) translateY(0px) scale(10)"}, - {transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing}, - {opacity: "0"}, - {zIndex: "500"} - ]); - this.currentTiddlerDomNode = toWidgetDomNode; + if (toWidgetDomNode.nodeType === Node.TEXT_NODE) { + this.logTextNodeRoot(toWidgetDomNode); + toWidgetDomNode = null; + } else { + $tw.utils.addClass(toWidgetDomNode,"tc-storyview-zoomin-tiddler"); + $tw.utils.setStyle(toWidgetDomNode,[ + {display: "block"}, + {transformOrigin: "50% 50%"}, + {transform: "translateX(0px) translateY(0px) scale(10)"}, + {transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", opacity " + duration + "ms " + easing}, + {opacity: "0"}, + {zIndex: "500"} + ]); + this.currentTiddlerDomNode = toWidgetDomNode; + } } // Animate them both // Force layout @@ -206,6 +221,10 @@ ZoominListView.prototype.remove = function(widget) { return true; // Indicate that we'll delete the DOM node }; +ZoominListView.prototype.logTextNodeRoot = function(node) { + this.textNodeLogger.log($tw.language.getString("Error/ZoominTextNode") + " " + node.textContent); +}; + exports.zoomin = ZoominListView; })(); diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 595f35a7f..f7627e1ac 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -24,7 +24,7 @@ Syncer.prototype.titleSyncPollingInterval = "$:/config/SyncPollingInterval"; Syncer.prototype.titleSyncDisableLazyLoading = "$:/config/SyncDisableLazyLoading"; Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done"; Syncer.prototype.titleSyncThrottleInterval = "$:/config/SyncThrottleInterval"; -Syncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer +Syncer.prototype.taskTimerInterval = 0.25 * 1000; // Interval for sync timer Syncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s... Syncer.prototype.errorRetryInterval = 5 * 1000; // Interval to retry after an error Syncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s @@ -74,9 +74,11 @@ function Syncer(options) { this.titlesHaveBeenLazyLoaded = {}; // Hashmap of titles of tiddlers that have already been lazily loaded from the server // Timers this.taskTimerId = null; // Timer for task dispatch - this.pollTimerId = null; // Timer for polling server // Number of outstanding requests this.numTasksInProgress = 0; + // True when we want to force an immediate sync from the server + this.forceSyncFromServer = false; + this.timestampLastSyncFromServer = new Date(); // Listen out for changes to tiddlers this.wiki.addEventListener("change",function(changes) { // Filter the changes to just include ones that are being synced @@ -203,33 +205,37 @@ Syncer.prototype.readTiddlerInfo = function() { Checks whether the wiki is dirty (ie the window shouldn't be closed) */ Syncer.prototype.isDirty = function() { - this.logger.log("Checking dirty status"); - // Check tiddlers that are in the store and included in the filter function - var titles = this.getSyncedTiddlers(); - for(var index=0; index tiddlerInfo.changeCount) { + var self = this; + function checkIsDirty() { + // Check tiddlers that are in the store and included in the filter function + var titles = self.getSyncedTiddlers(); + for(var index=0; index tiddlerInfo.changeCount) { + return true; + } + } else { + // If the tiddler isn't known on the server then it needs to be saved to the server return true; } - } else { - // If the tiddler isn't known on the server then it needs to be saved to the server + } + } + // Check tiddlers that are known from the server but not currently in the store + titles = Object.keys(self.tiddlerInfo); + for(index=0; index 0 || updates.deletions.length > 0) { - self.processTaskQueue(); - } - } - }); - } else if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) { - this.logger.log("Retrieving skinny tiddler list"); - cancelNextSync(); - this.syncadaptor.getSkinnyTiddlers(function(err,tiddlers) { - triggerNextSync(); - // Check for errors - if(err) { - self.displayError($tw.language.getString("Error/RetrievingSkinny"),err); - return; - } - // Keep track of which tiddlers we already know about have been reported this time - var previousTitles = Object.keys(self.tiddlerInfo); - // Process each incoming tiddler - for(var t=0; t= (this.timestampLastSyncFromServer.valueOf() + this.pollTimerInterval)))) { + return new SyncFromServerTask(this); + } + // Third, we check tiddlers that are known from the server but not currently in the store, and so need deleting on the server titles = Object.keys(this.tiddlerInfo); for(index=0; index 0) { + for(var t=this.requests.length - 1; t--; t>=0) { + var requestInfo = this.requests[t]; + requestInfo.request.cancel(); + } + } + this.requests = []; + this.updateRequestTracker(); +}; + +HttpClient.prototype.cancelHttpRequest = function(targetId) { + var targetIndex = this.getRequestIndex(targetId); + if(targetIndex !== null) { + this.requests[targetIndex].request.cancel(); + this.requests.splice(targetIndex,1); + this.updateRequestTracker(); + } +}; + +/* +Initiate an HTTP request. Options: +wiki: wiki to be used for executing action strings +url: URL for request +method: method eg GET, POST +body: text of request body +binary: set to "yes" to force binary processing of response payload +oncompletion: action string to be invoked on completion +onprogress: action string to be invoked on progress updates +bindStatus: optional title of tiddler to which status ("pending", "complete", "error") should be written +bindProgress: optional title of tiddler to which the progress of the request (0 to 100) should be bound +variables: hashmap of variable name to string value passed to action strings +headers: hashmap of header name to header value to be sent with the request +passwordHeaders: hashmap of header name to password store name to be sent with the request +queryStrings: hashmap of query string parameter name to parameter value to be sent with the request +passwordQueryStrings: hashmap of query string parameter name to password store name to be sent with the request +*/ +function HttpClientRequest(options) { + var self = this; + console.log("Initiating an HTTP request",options) + this.wiki = options.wiki; + this.completionActions = options.oncompletion; + this.progressActions = options.onprogress; + this.bindStatus = options["bindStatus"]; + this.bindProgress = options["bindProgress"]; + this.method = options.method || "GET"; + this.body = options.body || ""; + this.binary = options.binary || ""; + this.variables = options.variables; + var url = options.url; + $tw.utils.each(options.queryStrings,function(value,name) { + url = $tw.utils.setQueryStringParameter(url,name,value); + }); + $tw.utils.each(options.passwordQueryStrings,function(value,name) { + url = $tw.utils.setQueryStringParameter(url,name,$tw.utils.getPassword(value) || ""); + }); + this.url = url; + this.requestHeaders = {}; + $tw.utils.each(options.headers,function(value,name) { + self.requestHeaders[name] = value; + }); + $tw.utils.each(options.passwordHeaders,function(value,name) { + self.requestHeaders[name] = $tw.utils.getPassword(value) || ""; + }); +} + +HttpClientRequest.prototype.send = function(callback) { + var self = this, + setBinding = function(title,text) { + if(title) { + self.wiki.addTiddler(new $tw.Tiddler({title: title, text: text})); + } + }; + if(this.url) { + setBinding(this.bindStatus,"pending"); + setBinding(this.bindProgress,"0"); + // Set the request tracker tiddler + var requestTrackerTitle = this.wiki.generateNewTitle("$:/temp/HttpRequest"); + this.wiki.addTiddler({ + title: requestTrackerTitle, + tags: "$:/tags/HttpRequest", + text: JSON.stringify({ + url: this.url, + type: this.method, + status: "inprogress", + headers: this.requestHeaders, + data: this.body + }) + }); + this.xhr = $tw.utils.httpRequest({ + url: this.url, + type: this.method, + headers: this.requestHeaders, + data: this.body, + returnProp: this.binary === "" ? "responseText" : "response", + responseType: this.binary === "" ? "text" : "arraybuffer", + callback: function(err,data,xhr) { + var hasSucceeded = xhr.status >= 200 && xhr.status < 300, + completionCode = hasSucceeded ? "complete" : "error", + headers = {}; + $tw.utils.each(xhr.getAllResponseHeaders().split("\r\n"),function(line) { + var pos = line.indexOf(":"); + if(pos !== -1) { + headers[line.substr(0,pos)] = line.substr(pos + 1).trim(); + } + }); + setBinding(self.bindStatus,completionCode); + setBinding(self.bindProgress,"100"); + var resultVariables = { + status: xhr.status.toString(), + statusText: xhr.statusText, + error: (err || "").toString(), + data: (data || "").toString(), + headers: JSON.stringify(headers) + }; + /* Convert data from binary to base64 */ + if (xhr.responseType === "arraybuffer") { + var binary = "", + bytes = new Uint8Array(data), + len = bytes.byteLength; + for (var i=0; i 1) { nextEntry.shift(); prevEntry.shift(); } else { - list.next[value] = undefined; - list.prev[value] = undefined; + list.next.set(value,undefined); + list.prev.set(value,undefined); } list.length -= 1; }; // Sticks the given node onto the end of the list. function _linkToEnd(list,value) { - if(list.first === undefined) { - list.first = value; + var old = list.next.get(value); + var last = list.prev.get(null); + // Does it already exists? + if(old !== undefined) { + if(!Array.isArray(old)) { + old = [old]; + list.next.set(value,old); + list.prev.set(value,[list.prev.get(value)]); + } + old.push(null); + list.prev.get(value).push(last); } else { - // Does it already exists? - if(list.first === value || list.prev[value] !== undefined) { - if(typeof list.next[value] === "string") { - list.next[value] = [list.next[value]]; - list.prev[value] = [list.prev[value]]; - } else if(typeof list.next[value] === "undefined") { - // list.next[value] must be undefined. - // Special case. List already has 1 value. It's at the end. - list.next[value] = []; - list.prev[value] = [list.prev[value]]; - } - list.prev[value].push(list.last); - // We do NOT append a new value onto "next" list. Iteration will - // figure out it must point to End-of-List on its own. - } else { - list.prev[value] = list.last; - } - // Make the old last point to this new one. - if(typeof list.next[list.last] === "object") { - list.next[list.last].push(value); - } else { - list.next[list.last] = value; - } + list.next.set(value,null); + list.prev.set(value,last); + } + // Make the old last point to this new one. + if(value !== last) { + var array = list.next.get(last); + if(Array.isArray(array)) { + array[array.length-1] = value; + } else { + list.next.set(last,value); + } + list.prev.set(null,value); + } else { + // Edge case, the pushed value was already the last value. + // The second-to-last nextPtr for that value must point to itself now. + var array = list.next.get(last); + array[array.length-2] = value; } - list.last = value; list.length += 1; }; @@ -199,6 +189,20 @@ function _assertString(value) { } }; +var LLMap = function() { + this.map = Object.create(null); +}; + +// Just a wrapper so our object map can also accept null. +LLMap.prototype = { + set: function(key,val) { + (key === null) ? (this.null = val) : (this.map[key] = val); + }, + get: function(key) { + return (key === null) ? this.null : this.map[key]; + } +}; + exports.LinkedList = LinkedList; })(); diff --git a/core/modules/utils/utils.js b/core/modules/utils/utils.js index 743061ca7..9fffb1714 100644 --- a/core/modules/utils/utils.js +++ b/core/modules/utils/utils.js @@ -685,9 +685,19 @@ exports.escapeRegExp = function(s) { return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&'); }; +/* +Extended version of encodeURIComponent that encodes additional characters including +those that are illegal within filepaths on various platforms including Windows +*/ +exports.encodeURIComponentExtended = function(s) { + return encodeURIComponent(s).replace(/[!'()*]/g,function(c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +}; + // Checks whether a link target is external, i.e. not a tiddler title exports.isLinkExternal = function(to) { - var externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\s<>{}\[\]`|"\\^]+(?:\/|\b)/i; + var externalRegExp = /^(?:file|http|https|mailto|ftp|irc|news|obsidian|data|skype):[^\s<>{}\[\]`|"\\^]+(?:\/|\b)/i; return externalRegExp.test(to); }; @@ -809,18 +819,41 @@ exports.hashString = function(str) { },0); }; +/* +Base64 utility functions that work in either browser or Node.js +*/ +if(typeof window !== 'undefined') { + exports.btoa = function(binstr) { return window.btoa(binstr); } + exports.atob = function(b64) { return window.atob(b64); } +} else { + exports.btoa = function(binstr) { + return Buffer.from(binstr, 'binary').toString('base64'); + } + exports.atob = function(b64) { + return Buffer.from(b64, 'base64').toString('binary'); + } +} + /* Decode a base64 string */ -exports.base64Decode = function(string64) { - return base64utf8.base64.decode.call(base64utf8,string64); +exports.base64Decode = function(string64,binary,urlsafe) { + var encoded = urlsafe ? string64.replace(/_/g,'/').replace(/-/g,'+') : string64; + if(binary) return exports.atob(encoded) + else return base64utf8.base64.decode.call(base64utf8,encoded); }; /* Encode a string to base64 */ -exports.base64Encode = function(string64) { - return base64utf8.base64.encode.call(base64utf8,string64); +exports.base64Encode = function(string64,binary,urlsafe) { + var encoded; + if(binary) encoded = exports.btoa(string64); + else encoded = base64utf8.base64.encode.call(base64utf8,string64); + if(urlsafe) { + encoded = encoded.replace(/\+/g,'-').replace(/\//g,'_'); + } + return encoded; }; /* diff --git a/core/modules/widgets/action-popup.js b/core/modules/widgets/action-popup.js index 2903532b6..a3ce20165 100644 --- a/core/modules/widgets/action-popup.js +++ b/core/modules/widgets/action-popup.js @@ -14,6 +14,8 @@ Action widget to trigger a popup. var Widget = require("$:/core/modules/widgets/widget.js").widget; +var Popup = require("$:/core/modules/utils/dom/popup.js"); + var ActionPopupWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); }; @@ -57,20 +59,20 @@ 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 || ""); - if(match) { + var coordinates = Popup.parseCoordinates(this.actionCoords || ""); + if(coordinates) { $tw.popup.triggerPopup({ domNode: null, domNodeRect: { - left: parseFloat(match[1]), - top: parseFloat(match[2]), - width: parseFloat(match[3]), - height: parseFloat(match[4]) + left: coordinates.left, + top: coordinates.top, + width: coordinates.width, + height: coordinates.height }, title: this.actionState, wiki: this.wiki, - floating: this.floating + floating: this.floating, + absolute: coordinates.absolute }); } else { $tw.popup.cancel(0); diff --git a/core/modules/widgets/browse.js b/core/modules/widgets/browse.js index de3c91fb8..8130825b0 100644 --- a/core/modules/widgets/browse.js +++ b/core/modules/widgets/browse.js @@ -70,6 +70,11 @@ BrowseWidget.prototype.render = function(parent,nextSibling) { } return false; },false); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert element parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -95,6 +100,11 @@ BrowseWidget.prototype.execute = function() { Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ BrowseWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if($tw.utils.count(changedAttributes) > 0) { + this.refreshSelf(); + return true; + } return false; }; diff --git a/core/modules/widgets/button.js b/core/modules/widgets/button.js index a32820e8b..958b6f6da 100644 --- a/core/modules/widgets/button.js +++ b/core/modules/widgets/button.js @@ -14,6 +14,8 @@ Button widget var Widget = require("$:/core/modules/widgets/widget.js").widget; +var Popup = require("$:/core/modules/utils/dom/popup.js"); + var ButtonWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); }; @@ -57,6 +59,11 @@ ButtonWidget.prototype.render = function(parent,nextSibling) { $tw.utils.pushTop(classes,"tc-popup-handle"); } domNode.className = classes.join(" "); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Assign other attributes if(this.style) { domNode.setAttribute("style",this.style); @@ -147,7 +154,7 @@ ButtonWidget.prototype.isSelected = function() { ButtonWidget.prototype.isPoppedUp = function() { var tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup); - var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false; + var result = tiddler && tiddler.fields.text ? Popup.readPopupState(tiddler.fields.text) : false; return result; }; @@ -173,6 +180,7 @@ ButtonWidget.prototype.triggerPopup = function(event) { if(this.popupTitle) { $tw.popup.triggerPopup({ domNode: this.domNodes[0], + absolute: (this.popupAbsCoords === "yes"), title: this.popupTitle, wiki: this.wiki, noStateReference: true @@ -180,6 +188,7 @@ ButtonWidget.prototype.triggerPopup = function(event) { } else { $tw.popup.triggerPopup({ domNode: this.domNodes[0], + absolute: (this.popupAbsCoords === "yes"), title: this.popup, wiki: this.wiki }); @@ -223,6 +232,7 @@ ButtonWidget.prototype.execute = function() { this.setField = this.getAttribute("setField"); this.setIndex = this.getAttribute("setIndex"); this.popupTitle = this.getAttribute("popupTitle"); + this.popupAbsCoords = this.getAttribute("popupAbsCoords", "no"); this.tabIndex = this.getAttribute("tabindex"); this.isDisabled = this.getAttribute("disabled","no"); // Make child widgets @@ -245,18 +255,25 @@ ButtonWidget.prototype.updateDomNodeClasses = function() { //Add new classes from updated class attribute. $tw.utils.pushTop(domNodeClasses,newClasses); this.domNode.className = domNodeClasses.join(" "); -} +}; /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ ButtonWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) { + if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) { this.refreshSelf(); return true; - } else if(changedAttributes["class"]) { - this.updateDomNodeClasses(); + } else { + if(changedAttributes["class"]) { + this.updateDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/checkbox.js b/core/modules/widgets/checkbox.js index 68ebe7980..e07513b0a 100644 --- a/core/modules/widgets/checkbox.js +++ b/core/modules/widgets/checkbox.js @@ -53,6 +53,11 @@ CheckboxWidget.prototype.render = function(parent,nextSibling) { this.labelDomNode.appendChild(this.inputDomNode); this.spanDomNode = this.document.createElement("span"); this.labelDomNode.appendChild(this.spanDomNode); + // Assign data- attributes + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ {name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"} @@ -112,11 +117,11 @@ CheckboxWidget.prototype.getValue = function() { var list; if(this.checkboxListField) { if($tw.utils.hop(tiddler.fields,this.checkboxListField)) { - list = tiddler.getFieldList(this.checkboxListField); + list = tiddler.getFieldList(this.checkboxListField) || []; } else { list = $tw.utils.parseStringArray(this.checkboxDefault || "") || []; } - } else if (this.checkboxListIndex) { + } else if(this.checkboxListIndex) { list = $tw.utils.parseStringArray(this.wiki.extractTiddlerDataItem(tiddler,this.checkboxListIndex,this.checkboxDefault || "")) || []; } else { list = this.wiki.filterTiddlers(this.checkboxFilter,this) || []; @@ -208,16 +213,22 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) { if(this.checkboxListField || this.checkboxListIndex) { var fieldContents, listContents, oldPos, newPos; if(this.checkboxListField) { - fieldContents = tiddler ? tiddler.fields[this.checkboxListField] : undefined; + fieldContents = (tiddler ? tiddler.fields[this.checkboxListField] : undefined) || []; } else { fieldContents = this.wiki.extractTiddlerDataItem(this.checkboxTitle,this.checkboxListIndex); } if($tw.utils.isArray(fieldContents)) { // Make a copy so we can modify it without changing original that's refrenced elsewhere listContents = fieldContents.slice(0); - } else { - listContents = $tw.utils.parseStringArray(fieldContents) || []; + } else if(fieldContents === undefined) { + listContents = []; + } else if(typeof fieldContents === "string") { + listContents = $tw.utils.parseStringArray(fieldContents); // No need to copy since parseStringArray returns a fresh array, not refrenced elsewhere + } else { + // Field was neither an array nor a string; it's probably something that shouldn't become + // an array (such as a date field), so bail out *without* triggering actions + return; } oldPos = notValue ? listContents.indexOf(notValue) : -1; newPos = value ? listContents.indexOf(value) : -1; @@ -319,6 +330,11 @@ CheckboxWidget.prototype.refresh = function(changedTiddlers) { $tw.utils.removeClass(this.labelDomNode,"tc-checkbox-checked"); } } + this.assignAttributes(this.inputDomNode,{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); return this.refreshChildren(changedTiddlers) || refreshed; } }; @@ -326,3 +342,4 @@ CheckboxWidget.prototype.refresh = function(changedTiddlers) { exports.checkbox = CheckboxWidget; })(); + \ No newline at end of file diff --git a/core/modules/widgets/diff-text.js b/core/modules/widgets/diff-text.js index 0dca1042c..47a47e259 100644 --- a/core/modules/widgets/diff-text.js +++ b/core/modules/widgets/diff-text.js @@ -39,7 +39,7 @@ DiffTextWidget.prototype.render = function(parent,nextSibling) { this.execute(); // Create the diff var dmpObject = new dmp.diff_match_patch(), - diffs = dmpObject.diff_main(this.getAttribute("source"),this.getAttribute("dest")); + diffs = dmpObject.diff_main(this.getAttribute("source",""),this.getAttribute("dest","")); // Apply required cleanup switch(this.getAttribute("cleanup","semantic")) { case "none": diff --git a/core/modules/widgets/draggable.js b/core/modules/widgets/draggable.js index f759ab121..22fdc37e9 100644 --- a/core/modules/widgets/draggable.js +++ b/core/modules/widgets/draggable.js @@ -52,6 +52,11 @@ DraggableWidget.prototype.render = function(parent,nextSibling) { classes.push("tc-draggable"); } domNode.setAttribute("class",classes.join(" ")); + // Assign data- attributes and style. attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert the node into the DOM and render any children parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -108,13 +113,19 @@ DraggableWidget.prototype.updateDomNodeClasses = function() { Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ DraggableWidget.prototype.refresh = function(changedTiddlers) { - var changedAttributes = this.computeAttributes(), - changedAttributesCount = $tw.utils.count(changedAttributes); - if(changedAttributesCount === 1 && changedAttributes["class"]) { - this.updateDomNodeClasses(); - } else if(changedAttributesCount > 0) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes.tag || changedAttributes.selector || changedAttributes.dragimagetype || changedAttributes.enable || changedAttributes.startactions || changedAttributes.endactions) { this.refreshSelf(); return true; + } else { + if(changedAttributes["class"]) { + this.assignDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/droppable.js b/core/modules/widgets/droppable.js index 104503b25..0dcba1688 100644 --- a/core/modules/widgets/droppable.js +++ b/core/modules/widgets/droppable.js @@ -42,6 +42,11 @@ DroppableWidget.prototype.render = function(parent,nextSibling) { domNode = this.document.createElement(tag); this.domNode = domNode; this.assignDomNodeClasses(); + // Assign data- attributes and style. attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add event handlers if(this.droppableEnable) { $tw.utils.addEventListeners(domNode,[ @@ -166,8 +171,15 @@ DroppableWidget.prototype.refresh = function(changedTiddlers) { if(changedAttributes.tag || changedAttributes.enable || changedAttributes.disabledClass || changedAttributes.actions || changedAttributes.effect) { this.refreshSelf(); return true; - } else if(changedAttributes["class"]) { - this.assignDomNodeClasses(); + } else { + if(changedAttributes["class"]) { + this.assignDomNodeClasses(); + } + this.assignAttributes(this.domNodes[0],{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/dropzone.js b/core/modules/widgets/dropzone.js index efa08162c..043b2557f 100644 --- a/core/modules/widgets/dropzone.js +++ b/core/modules/widgets/dropzone.js @@ -232,12 +232,34 @@ DropZoneWidget.prototype.handleDropEvent = function(event) { }; DropZoneWidget.prototype.handlePasteEvent = function(event) { - var self = this, - readFileCallback = function(tiddlerFieldsArray) { + var self = this; + var readFileCallback = function(tiddlerFieldsArray) { self.readFileCallback(tiddlerFieldsArray); }; + var getItem = function(type) { + type = type || "text/plain"; + return function(str) { + // Use the deserializer specified if any + if(self.dropzoneDeserializer) { + tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled " + type)},{deserializer:self.dropzoneDeserializer}); + if(tiddlerFields && tiddlerFields.length) { + readFileCallback(tiddlerFields); + } + } else { + tiddlerFields = { + title: self.wiki.generateNewTitle("Untitled " + type), + text: str, + type: type + }; + if($tw.log.IMPORT) { + console.log("Importing string '" + str + "', type: '" + type + "'"); + } + readFileCallback([tiddlerFields]); + } + } + }; // Let the browser handle it if we're in a textarea or input box - if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable) { + if(["TEXTAREA","INPUT"].indexOf(event.target.tagName) == -1 && !event.target.isContentEditable && !event.twEditor) { var self = this, items = event.clipboardData.items; // Enumerate the clipboard items @@ -249,29 +271,26 @@ DropZoneWidget.prototype.handlePasteEvent = function(event) { callback: readFileCallback, deserializer: this.dropzoneDeserializer }); - } else if(item.kind === "string") { - // Create tiddlers from string items - var tiddlerFields, - type = item.type; - item.getAsString(function(str) { - // Use the deserializer specified if any - if(self.dropzoneDeserializer) { - tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: self.wiki.generateNewTitle("Untitled")},{deserializer:self.dropzoneDeserializer}); + } else if(item.kind === "string" && !["text/html", "text/plain", "Text"].includes(item.type) && $tw.utils.itemHasValidDataType(item)) { + // Try to import the various data types we understand + var fallbackTitle = self.wiki.generateNewTitle("Untitled"); + //Use the deserializer specified if any + if(this.dropzoneDeserializer) { + item.getAsString(function(str){ + var tiddlerFields = self.wiki.deserializeTiddlers(null,str,{title: fallbackTitle},{deserializer:self.dropzoneDeserializer}); if(tiddlerFields && tiddlerFields.length) { readFileCallback(tiddlerFields); } - } else { - tiddlerFields = { - title: self.wiki.generateNewTitle("Untitled"), - text: str, - type: type - }; - if($tw.log.IMPORT) { - console.log("Importing string '" + str + "', type: '" + type + "'"); - } - readFileCallback([tiddlerFields]); - } - }); + }); + } else { + $tw.utils.importPaste(item,fallbackTitle,readFileCallback); + } + } else if(item.kind === "string") { + // Create tiddlers from string items + var tiddlerFields; + // It's important to give getAsString a closure with the right type + // So it can be added to the import queue + item.getAsString(getItem(item.type)); } } // Tell the browser that we've handled the paste diff --git a/core/modules/widgets/edit.js b/core/modules/widgets/edit.js index e7bd49b93..eb7758e90 100644 --- a/core/modules/widgets/edit.js +++ b/core/modules/widgets/edit.js @@ -90,7 +90,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of EditWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Refresh if an attribute has changed, or the type associated with the target tiddler has changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (this.getEditorType() !== this.editorType)) { this.refreshSelf(); return true; } else { diff --git a/core/modules/widgets/element.js b/core/modules/widgets/element.js index c3d6c96d9..716886e5b 100755 --- a/core/modules/widgets/element.js +++ b/core/modules/widgets/element.js @@ -34,6 +34,10 @@ ElementWidget.prototype.render = function(parent,nextSibling) { if($tw.config.htmlUnsafeElements.indexOf(this.tag) !== -1) { this.tag = "safe-" + this.tag; } + // Restrict tag name to digits, letts and dashes + this.tag = this.tag.replace(/[^0-9a-zA-Z\-]/mg,""); + // Default to a span + this.tag = this.tag || "span"; // Adjust headings by the current base level var headingLevel = ["h1","h2","h3","h4","h5","h6"].indexOf(this.tag); if(headingLevel !== -1) { diff --git a/core/modules/widgets/fill.js b/core/modules/widgets/fill.js new file mode 100644 index 000000000..de88c95af --- /dev/null +++ b/core/modules/widgets/fill.js @@ -0,0 +1,30 @@ +/*\ +title: $:/core/modules/widgets/fill.js +type: application/javascript +module-type: widget + +Sub-widget used by the transclude widget for specifying values for slots within transcluded content. It doesn't do anything by itself because the transclude widget only ever deals with the parse tree nodes, and doesn't instantiate the widget itself + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var FillWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +FillWidget.prototype = new Widget(); + +exports.fill = FillWidget; + +})(); + \ No newline at end of file diff --git a/core/modules/widgets/genesis.js b/core/modules/widgets/genesis.js index 51544361e..c8403a3d4 100644 --- a/core/modules/widgets/genesis.js +++ b/core/modules/widgets/genesis.js @@ -42,10 +42,16 @@ Compute the internal state of the widget GenesisWidget.prototype.execute = function() { var self = this; // Collect attributes - this.genesisType = this.getAttribute("$type","element"); + this.genesisType = this.getAttribute("$type"); this.genesisRemappable = this.getAttribute("$remappable","yes") === "yes"; this.genesisNames = this.getAttribute("$names",""); this.genesisValues = this.getAttribute("$values",""); + this.genesisIsBlock = this.getAttribute("$mode",this.parseTreeNode.isBlock && "block") === "block"; + // Do not create a child widget if the $type attribute is missing or blank + if(!this.genesisType) { + this.makeChildWidgets(this.parseTreeNode.children); + return; + } // Construct parse tree var isElementWidget = this.genesisType.charAt(0) !== "$", nodeType = isElementWidget ? "element" : this.genesisType.substr(1), @@ -55,6 +61,7 @@ GenesisWidget.prototype.execute = function() { tag: nodeTag, attributes: {}, orderedAttributes: [], + isBlock: this.genesisIsBlock, children: this.parseTreeNode.children || [], isNotRemappable: !this.genesisRemappable }]; diff --git a/core/modules/widgets/image.js b/core/modules/widgets/image.js index f14e84c44..52496fd74 100644 --- a/core/modules/widgets/image.js +++ b/core/modules/widgets/image.js @@ -58,24 +58,25 @@ ImageWidget.prototype.render = function(parent,nextSibling) { if(this.wiki.isImageTiddler(this.imageSource)) { var type = tiddler.fields.type, text = tiddler.fields.text, - _canonical_uri = tiddler.fields._canonical_uri; + _canonical_uri = tiddler.fields._canonical_uri, + typeInfo = $tw.config.contentTypeInfo[type] || {}, + deserializerType = typeInfo.deserializerType || type; // If the tiddler has body text then it doesn't need to be lazily loaded if(text) { - // Render the appropriate element for the image type - switch(type) { - case "application/pdf": + // Render the appropriate element for the image type by looking up the encoding in the content type info + var encoding = typeInfo.encoding || "utf8"; + if (encoding === "base64") { + // .pdf .png .jpg etc. + src = "data:" + deserializerType + ";base64," + text; + if (deserializerType === "application/pdf") { tag = "embed"; - src = "data:application/pdf;base64," + text; - break; - case "image/svg+xml": - src = "data:image/svg+xml," + encodeURIComponent(text); - break; - default: - src = "data:" + type + ";base64," + text; - break; + } + } else { + // .svg .tid .xml etc. + src = "data:" + deserializerType + "," + encodeURIComponent(text); } } else if(_canonical_uri) { - switch(type) { + switch(deserializerType) { case "application/pdf": tag = "embed"; src = _canonical_uri; @@ -99,6 +100,9 @@ ImageWidget.prototype.render = function(parent,nextSibling) { if(this.imageClass) { domNode.setAttribute("class",this.imageClass); } + if(this.imageUsemap) { + domNode.setAttribute("usemap",this.imageUsemap); + } if(this.imageWidth) { domNode.setAttribute("width",this.imageWidth); } @@ -138,6 +142,7 @@ ImageWidget.prototype.execute = function() { this.imageWidth = this.getAttribute("width"); this.imageHeight = this.getAttribute("height"); this.imageClass = this.getAttribute("class"); + this.imageUsemap = this.getAttribute("usemap"); this.imageTooltip = this.getAttribute("tooltip"); this.imageAlt = this.getAttribute("alt"); this.lazyLoading = this.getAttribute("loading"); @@ -148,7 +153,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ ImageWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) { + if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.usemap || changedAttributes.tooltip || changedTiddlers[this.imageSource]) { this.refreshSelf(); return true; } else { diff --git a/core/modules/widgets/importvariables.js b/core/modules/widgets/importvariables.js index a73abfdcf..a8bb483b6 100644 --- a/core/modules/widgets/importvariables.js +++ b/core/modules/widgets/importvariables.js @@ -49,41 +49,47 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { this.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this); // Accumulate the <$set> widgets from each tiddler $tw.utils.each(this.tiddlerList,function(title) { - var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true}); + var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:true}); if(parser) { var parseTreeNode = parser.tree[0]; - while(parseTreeNode && parseTreeNode.type === "set") { + while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) { var node = { type: "set", attributes: parseTreeNode.attributes, params: parseTreeNode.params, - isMacroDefinition: parseTreeNode.isMacroDefinition + isMacroDefinition: parseTreeNode.isMacroDefinition, + isFunctionDefinition: parseTreeNode.isFunctionDefinition, + isProcedureDefinition: parseTreeNode.isProcedureDefinition, + isWidgetDefinition: parseTreeNode.isWidgetDefinition, + configTrimWhiteSpace: parseTreeNode.configTrimWhiteSpace }; - if (parseTreeNode.isMacroDefinition) { - // Macro definitions can be folded into - // current widget instead of adding - // another link to the chain. - var widget = widgetPointer.makeChildWidget(node); - widget.computeAttributes(); - widget.execute(); - // We SHALLOW copy over all variables - // in widget. We can't use - // $tw.utils.assign, because that copies - // up the prototype chain, which we - // don't want. - $tw.utils.each(Object.keys(widget.variables), function(key) { - widgetPointer.variables[key] = widget.variables[key]; - }); - } else { - widgetPointer.children = [widgetPointer.makeChildWidget(node)]; - // No more regenerating children for - // this widget. If it needs to refresh, - // it'll do so along with the the whole - // importvariable tree. - if (widgetPointer != this) { - widgetPointer.makeChildWidgets = function(){}; + if(parseTreeNode.type === "set" || parseTreeNode.type === "setvariable") { + if(parseTreeNode.isMacroDefinition || parseTreeNode.isProcedureDefinition || parseTreeNode.isWidgetDefinition || parseTreeNode.isFunctionDefinition) { + // Macro definitions can be folded into + // current widget instead of adding + // another link to the chain. + var widget = widgetPointer.makeChildWidget(node); + widget.computeAttributes(); + widget.execute(); + // We SHALLOW copy over all variables + // in widget. We can't use + // $tw.utils.assign, because that copies + // up the prototype chain, which we + // don't want. + $tw.utils.each(Object.keys(widget.variables), function(key) { + widgetPointer.variables[key] = widget.variables[key]; + }); + } else { + widgetPointer.children = [widgetPointer.makeChildWidget(node)]; + // No more regenerating children for + // this widget. If it needs to refresh, + // it'll do so along with the the whole + // importvariable tree. + if (widgetPointer != this) { + widgetPointer.makeChildWidgets = function(){}; + } + widgetPointer = widgetPointer.children[0]; } - widgetPointer = widgetPointer.children[0]; } parseTreeNode = parseTreeNode.children && parseTreeNode.children[0]; } diff --git a/core/modules/widgets/let.js b/core/modules/widgets/let.js index afd3a2f20..2b2886530 100644 --- a/core/modules/widgets/let.js +++ b/core/modules/widgets/let.js @@ -53,7 +53,9 @@ LetWidget.prototype.computeAttributes = function() { name = attribute.name; // Now that it's prepped, we're allowed to look this variable up // when defining later variables - self.currentValueFor[name] = value; + if(value !== undefined) { + self.currentValueFor[name] = value; + } }); // Run through again, setting variables and looking for differences $tw.utils.each(this.currentValueFor,function(value,name) { diff --git a/core/modules/widgets/link.js b/core/modules/widgets/link.js index 16356ee01..f02a7cae2 100755 --- a/core/modules/widgets/link.js +++ b/core/modules/widgets/link.js @@ -43,6 +43,11 @@ LinkWidget.prototype.render = function(parent,nextSibling) { } else { // Just insert the link text var domNode = this.document.createElement("span"); + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); this.domNodes.push(domNode); @@ -97,8 +102,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) { // Expand the tv-wikilink-template variable to construct the href var wikiLinkTemplateMacro = this.getVariable("tv-wikilink-template"), wikiLinkTemplate = wikiLinkTemplateMacro ? wikiLinkTemplateMacro.trim() : "#$uri_encoded$"; - wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",encodeURIComponent(this.to)); - wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",encodeURIComponent(encodeURIComponent(this.to))); + wikiLinkText = $tw.utils.replaceString(wikiLinkTemplate,"$uri_encoded$",$tw.utils.encodeURIComponentExtended(this.to)); + wikiLinkText = $tw.utils.replaceString(wikiLinkText,"$uri_doubleencoded$",$tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.to))); } // Override with the value of tv-get-export-link if defined wikiLinkText = this.getVariable("tv-get-export-link",{params: [{name: "to",value: this.to}],defaultValue: wikiLinkText}); @@ -138,6 +143,11 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) { widget: this }); } + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Insert the link into the DOM and render any children parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -207,8 +217,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ LinkWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.to || changedTiddlers[this.to] || changedAttributes["aria-label"] || changedAttributes.tooltip || - changedAttributes["class"] || changedAttributes.tabindex || changedAttributes.draggable || changedAttributes.tag) { + if($tw.utils.count(changedAttributes) > 0 || changedTiddlers[this.to]) { this.refreshSelf(); return true; } @@ -218,3 +227,4 @@ LinkWidget.prototype.refresh = function(changedTiddlers) { exports.link = LinkWidget; })(); + \ No newline at end of file diff --git a/core/modules/widgets/linkcatcher.js b/core/modules/widgets/linkcatcher.js index 78322d0f6..4f4a66b17 100644 --- a/core/modules/widgets/linkcatcher.js +++ b/core/modules/widgets/linkcatcher.js @@ -92,12 +92,9 @@ LinkCatcherWidget.prototype.handleNavigateEvent = function(event) { this.executingActions = false; } } else { - // This is a navigate event generated by the actions of this linkcatcher, so we don't trap it again, but just pass it to the parent - this.parentWidget.dispatchEvent({ - type: "tm-navigate", - param: event.navigateTo, - navigateTo: event.navigateTo - }); + // This is a navigate event generated by the actions of this linkcatcher, + // so we don't trap it again, but just pass it to the parent + this.parentWidget.dispatchEvent(event); } return false; }; diff --git a/core/modules/widgets/list.js b/core/modules/widgets/list.js index 41344a02e..d4ad41995 100755 --- a/core/modules/widgets/list.js +++ b/core/modules/widgets/list.js @@ -28,6 +28,18 @@ Inherit from the base widget class */ ListWidget.prototype = new Widget(); +ListWidget.prototype.initialise = function(parseTreeNode,options) { + // Bail if parseTreeNode is undefined, meaning that the ListWidget constructor was called without any arguments so that it can be subclassed + if(parseTreeNode === undefined) { + return; + } + // First call parent constructor to set everything else up + Widget.prototype.initialise.call(this,parseTreeNode,options); + // Now look for <$list-template> and <$list-empty> widgets as immediate child widgets + // This is safe to do during initialization because parse trees never change after creation + this.findExplicitTemplates(); +} + /* Render this widget into the DOM */ @@ -38,8 +50,8 @@ ListWidget.prototype.render = function(parent,nextSibling) { $tw.modules.applyMethods("storyview",this.storyViews); } this.parentDomNode = parent; - this.computeAttributes(); - this.execute(); + var changedAttributes = this.computeAttributes(); + this.execute(changedAttributes); this.renderChildren(parent,nextSibling); // Construct the storyview var StoryView = this.storyViews[this.storyViewName]; @@ -59,7 +71,8 @@ ListWidget.prototype.render = function(parent,nextSibling) { /* Compute the internal state of the widget */ -ListWidget.prototype.execute = function() { +ListWidget.prototype.execute = function(changedAttributes) { + var self = this; // Get our attributes this.template = this.getAttribute("template"); this.editTemplate = this.getAttribute("editTemplate"); @@ -67,6 +80,10 @@ ListWidget.prototype.execute = function() { this.counterName = this.getAttribute("counter"); this.storyViewName = this.getAttribute("storyview"); this.historyTitle = this.getAttribute("history"); + // Create join template only if needed + if(this.join === undefined || (changedAttributes && changedAttributes.join)) { + this.join = this.makeJoinTemplate(); + } // Compose the list elements this.list = this.getTiddlerList(); var members = [], @@ -85,18 +102,57 @@ ListWidget.prototype.execute = function() { this.history = []; }; +ListWidget.prototype.findExplicitTemplates = function() { + var self = this; + this.explicitListTemplate = null; + this.explicitEmptyTemplate = null; + this.explicitJoinTemplate = null; + this.hasTemplateInBody = false; + var searchChildren = function(childNodes) { + var foundInlineTemplate = false; + $tw.utils.each(childNodes,function(node) { + if(node.type === "list-template") { + self.explicitListTemplate = node.children; + } else if(node.type === "list-empty") { + self.explicitEmptyTemplate = node.children; + } else if(node.type === "list-join") { + self.explicitJoinTemplate = node.children; + } else if(node.type === "element" && node.tag === "p") { + searchChildren(node.children); + foundInlineTemplate = true; + } else { + foundInlineTemplate = true; + } + }); + return foundInlineTemplate; + }; + this.hasTemplateInBody = searchChildren(this.parseTreeNode.children); +} + ListWidget.prototype.getTiddlerList = function() { + var limit = $tw.utils.getInt(this.getAttribute("limit",""),undefined); var defaultFilter = "[!is[system]sort[title]]"; - return this.wiki.filterTiddlers(this.getAttribute("filter",defaultFilter),this); + var results = this.wiki.filterTiddlers(this.getAttribute("filter",defaultFilter),this); + if(limit !== undefined) { + if(limit >= 0) { + results = results.slice(0,limit); + } else { + results = results.slice(limit); + } + } + return results; }; ListWidget.prototype.getEmptyMessage = function() { var parser, - emptyMessage = this.getAttribute("emptyMessage",""); - // this.wiki.parseText() calls - // new Parser(..), which should only be done, if needed, because it's heavy! - if (emptyMessage === "") { - return []; + emptyMessage = this.getAttribute("emptyMessage"); + // If emptyMessage attribute is not present or empty then look for an explicit empty template + if(!emptyMessage) { + if(this.explicitEmptyTemplate) { + return this.explicitEmptyTemplate; + } else { + return []; + } } parser = this.wiki.parseText("text/vnd.tiddlywiki",emptyMessage,{parseAsInline: true}); if(parser) { @@ -106,6 +162,24 @@ ListWidget.prototype.getEmptyMessage = function() { } }; +/* +Compose the template for a join between list items +*/ +ListWidget.prototype.makeJoinTemplate = function() { + var parser, + join = this.getAttribute("join",""); + if(join) { + parser = this.wiki.parseText("text/vnd.tiddlywiki",join,{parseAsInline:true}) + if(parser) { + return parser.tree; + } else { + return []; + } + } else { + return this.explicitJoinTemplate; // May be null, and that's fine + } +}; + /* Compose the template for a list item */ @@ -114,6 +188,7 @@ ListWidget.prototype.makeItemTemplate = function(title,index) { var tiddler = this.wiki.getTiddler(title), isDraft = tiddler && tiddler.hasField("draft.of"), template = this.template, + join = this.join, templateTree; if(isDraft && this.editTemplate) { template = this.editTemplate; @@ -122,22 +197,29 @@ ListWidget.prototype.makeItemTemplate = function(title,index) { if(template) { templateTree = [{type: "transclude", attributes: {tiddler: {type: "string", value: template}}}]; } else { + // Check for child nodes of the list widget if(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) { - templateTree = this.parseTreeNode.children; - } else { + // Check for a <$list-item> widget + if(this.explicitListTemplate) { + templateTree = this.explicitListTemplate; + } else if(this.hasTemplateInBody) { + templateTree = this.parseTreeNode.children; + } + } + if(!templateTree || templateTree.length === 0) { // Default template is a link to the title templateTree = [{type: "element", tag: this.parseTreeNode.isBlock ? "div" : "span", children: [{type: "link", attributes: {to: {type: "string", value: title}}, children: [ - {type: "text", text: title} + {type: "text", text: title} ]}]}]; } } // Return the list item - var parseTreeNode = {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree}; + var parseTreeNode = {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree, join: join}; + parseTreeNode.isLast = index === this.list.length - 1; if(this.counterName) { parseTreeNode.counter = (index + 1).toString(); parseTreeNode.counterName = this.counterName; parseTreeNode.isFirst = index === 0; - parseTreeNode.isLast = index === this.list.length - 1; } return parseTreeNode; }; @@ -153,7 +235,7 @@ ListWidget.prototype.refresh = function(changedTiddlers) { this.storyview.refreshStart(changedTiddlers,changedAttributes); } // Completely refresh if any of our attributes have changed - if(changedAttributes.filter || changedAttributes.variable || changedAttributes.counter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) { + if(changedAttributes.filter || changedAttributes.variable || changedAttributes.counter || changedAttributes.template || changedAttributes.editTemplate || changedAttributes.join || changedAttributes.emptyMessage || changedAttributes.storyview || changedAttributes.history) { this.refreshSelf(); result = true; } else { @@ -225,6 +307,8 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) { // If we are providing an counter variable then we must refresh the items, otherwise we can rearrange them var hasRefreshed = false,t; if(this.counterName) { + var mustRefreshOldLast = false; + var oldLength = this.children.length; // Cycle through the list and remove and re-insert the first item that has changed, and all the remaining items for(t=0; t 0) { + var oldLastIdx = oldLength-1; + this.removeListItem(oldLastIdx); + this.insertListItem(oldLastIdx,this.list[oldLastIdx]); + } // If there are items to remove and we have not refreshed then recreate the item that will now be at the last position if(!hasRefreshed && this.children.length > this.list.length) { this.removeListItem(this.list.length-1); @@ -246,10 +339,29 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) { } } else { // Cycle through the list, inserting and removing list items as needed + var mustRecreateLastItem = false; + if(this.join && this.join.length) { + if(this.children.length !== this.list.length) { + mustRecreateLastItem = true; + } else if(prevList[prevList.length-1] !== this.list[this.list.length-1]) { + mustRecreateLastItem = true; + } + } + var isLast = false, wasLast = false; for(t=0; t0) { + // First re-create previosly-last item that will no longer be last + this.removeListItem(t-1); + this.insertListItem(t-1,this.list[t-1]); + } this.insertListItem(t,this.list[t]); hasRefreshed = true; } else { @@ -258,9 +370,15 @@ ListWidget.prototype.handleListChanges = function(changedTiddlers) { this.removeListItem(n); hasRefreshed = true; } - // Refresh the item we're reusing - var refreshed = this.children[t].refresh(changedTiddlers); - hasRefreshed = hasRefreshed || refreshed; + // Refresh the item we're reusing, or recreate if necessary + if(mustRecreateLastItem && (isLast || wasLast)) { + this.removeListItem(t); + this.insertListItem(t,this.list[t]); + hasRefreshed = true; + } else { + var refreshed = this.children[t].refresh(changedTiddlers); + hasRefreshed = hasRefreshed || refreshed; + } } } } @@ -350,8 +468,17 @@ ListItemWidget.prototype.execute = function() { this.setVariable(this.parseTreeNode.counterName + "-first",this.parseTreeNode.isFirst ? "yes" : "no"); this.setVariable(this.parseTreeNode.counterName + "-last",this.parseTreeNode.isLast ? "yes" : "no"); } + // Add join if needed + var children = this.parseTreeNode.children, + join = this.parseTreeNode.join; + if(join && join.length && !this.parseTreeNode.isLast) { + children = children.slice(0); + $tw.utils.each(join,function(joinNode) { + children.push(joinNode); + }) + } // Construct the child widgets - this.makeChildWidgets(); + this.makeChildWidgets(children); }; /* @@ -363,4 +490,37 @@ ListItemWidget.prototype.refresh = function(changedTiddlers) { exports.listitem = ListItemWidget; +/* +Make <$list-template> and <$list-empty> widgets that do nothing +*/ +var ListTemplateWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListTemplateWidget.prototype = new Widget(); +ListTemplateWidget.prototype.render = function() {} +ListTemplateWidget.prototype.refresh = function() { return false; } + +exports["list-template"] = ListTemplateWidget; + +var ListEmptyWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListEmptyWidget.prototype = new Widget(); +ListEmptyWidget.prototype.render = function() {} +ListEmptyWidget.prototype.refresh = function() { return false; } + +exports["list-empty"] = ListEmptyWidget; + +var ListJoinWidget = function(parseTreeNode,options) { + // Main initialisation inherited from widget.js + this.initialise(parseTreeNode,options); +}; +ListJoinWidget.prototype = new Widget(); +ListJoinWidget.prototype.render = function() {} +ListJoinWidget.prototype.refresh = function() { return false; } + +exports["list-join"] = ListJoinWidget; + })(); diff --git a/core/modules/widgets/macrocall.js b/core/modules/widgets/macrocall.js index 9de2e5d67..2c4adc355 100644 --- a/core/modules/widgets/macrocall.js +++ b/core/modules/widgets/macrocall.js @@ -37,7 +37,7 @@ MacroCallWidget.prototype.render = function(parent,nextSibling) { Compute the internal state of the widget */ MacroCallWidget.prototype.execute = function() { - // Get the parse type if specified + this.macroName = this.parseTreeNode.name || this.getAttribute("$name"), this.parseType = this.getAttribute("$type","text/vnd.tiddlywiki"); this.renderOutput = this.getAttribute("$output","text/html"); // Merge together the parameters specified in the parse tree with the specified attributes @@ -47,49 +47,27 @@ MacroCallWidget.prototype.execute = function() { params.push({name: name, value: attribute}); } }); - // Get the macro value - var macroName = this.parseTreeNode.name || this.getAttribute("$name"), - variableInfo = this.getVariableInfo(macroName,{params: params}), - text = variableInfo.text, - parseTreeNodes; - // Are we rendering to HTML? - if(this.renderOutput === "text/html") { - // If so we'll return the parsed macro - // Check if we've already cached parsing this macro - var mode = this.parseTreeNode.isBlock ? "blockParser" : "inlineParser", - parser; - if(variableInfo.srcVariable && variableInfo.srcVariable[mode]) { - parser = variableInfo.srcVariable[mode]; - } else { - parser = this.wiki.parseText(this.parseType,text, - {parseAsInline: !this.parseTreeNode.isBlock}); - if(variableInfo.isCacheable && variableInfo.srcVariable) { - variableInfo.srcVariable[mode] = parser; - } - } - var parseTreeNodes = parser ? parser.tree : []; - // Wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__" - var attributes = {}; - $tw.utils.each(variableInfo.params,function(param) { - var name = "__" + param.name + "__"; - attributes[name] = { - name: name, - type: "string", - value: param.value - }; - }); + // Make a transclude widget + var positionalName = 0, parseTreeNodes = [{ - type: "vars", - attributes: attributes, - children: parseTreeNodes + type: "transclude", + isBlock: this.parseTreeNode.isBlock, + children: this.parseTreeNode.children }]; - } else if(this.renderOutput === "text/raw") { - parseTreeNodes = [{type: "text", text: text}]; - } else { - // Otherwise, we'll render the text - var plainText = this.wiki.renderText("text/plain",this.parseType,text,{parentWidget: this}); - parseTreeNodes = [{type: "text", text: plainText}]; - } + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$variable",this.macroName); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$type",this.parseType); + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"$output",this.renderOutput); + $tw.utils.each(params,function(param) { + var name = param.name; + if(name) { + if(name.charAt(0) === "$") { + name = "$" + name; + } + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],name,param.value); + } else { + $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],(positionalName++) + "",param.value); + } + }); // Construct the child widgets this.makeChildWidgets(parseTreeNodes); }; diff --git a/core/modules/widgets/messagecatcher.js b/core/modules/widgets/messagecatcher.js index 85a3561f2..1457cd11f 100644 --- a/core/modules/widgets/messagecatcher.js +++ b/core/modules/widgets/messagecatcher.js @@ -82,7 +82,7 @@ MessageCatcherWidget.prototype.render = function(parent,nextSibling) { } }); // Render children - this.renderChildren(parent,null); + this.renderChildren(parent,nextSibling); }; /* diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index 3f1efbe7a..efdbba83f 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -227,10 +227,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) { originalTitle = tiddler ? tiddler.fields["draft.of"] : "", originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined, confirmationTitle, - win = event.event && event.event.view ? event.event.view : window; - if(!tiddler) { - return false; - } + win = event.event && event.event.view ? event.event.view : window; // Check if the tiddler we're deleting is in draft mode if(originalTitle) { // If so, we'll prompt for confirmation referencing the original tiddler @@ -240,7 +237,7 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) { confirmationTitle = title; } // Seek confirmation - if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !win.confirm($tw.language.getString( + if(((originalTitle && this.wiki.getTiddler(originalTitle)) || (tiddler && ((tiddler.fields.text || "") !== ""))) && !win.confirm($tw.language.getString( "ConfirmDeleteTiddler", {variables: {title: confirmationTitle} @@ -257,8 +254,10 @@ NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) { this.removeTitleFromStory(storyList,originalTitle); } // Invoke the hook function and delete this tiddler - $tw.hooks.invokeHook("th-deleting-tiddler",tiddler); - this.wiki.deleteTiddler(title); + if(tiddler) { + $tw.hooks.invokeHook("th-deleting-tiddler",tiddler); + this.wiki.deleteTiddler(title); + } // Remove the closed tiddler from the story this.removeTitleFromStory(storyList,title); this.saveStoryList(storyList); @@ -500,7 +499,8 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) { // Get the tiddlers var tiddlers = $tw.utils.parseJSONSafe(event.param,[]); // Get the current $:/Import tiddler - var importTitle = event.importTitle ? event.importTitle : IMPORT_TITLE, + var paramObject = event.paramObject || {}, + importTitle = event.importTitle || paramObject.importTitle || IMPORT_TITLE, importTiddler = this.wiki.getTiddler(importTitle), importData = this.wiki.getTiddlerData(importTitle,{}), newFields = new Object({ @@ -541,7 +541,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) { newFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces); this.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields)); // Update the story and history details - var autoOpenOnImport = event.autoOpenOnImport ? event.autoOpenOnImport : this.getVariable("tv-auto-open-on-import"); + var autoOpenOnImport = event.autoOpenOnImport || paramObject.autoOpenOnImport || this.getVariable("tv-auto-open-on-import"); if(autoOpenOnImport !== "no") { var storyList = this.getStoryList(), history = []; diff --git a/core/modules/widgets/parameters.js b/core/modules/widgets/parameters.js new file mode 100644 index 000000000..69194cb9e --- /dev/null +++ b/core/modules/widgets/parameters.js @@ -0,0 +1,96 @@ +/*\ +title: $:/core/modules/widgets/parameters.js +type: application/javascript +module-type: widget + +Widget for definition of transclusion parameters + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude; + +var ParametersWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +ParametersWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +ParametersWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +ParametersWidget.prototype.execute = function() { + var self = this; + this.parametersDepth = Math.max(parseInt(this.getAttribute("$depth","1"),10) || 1,1); + // Find the parent transclusions + var pointer = this.parentWidget, + depth = this.parametersDepth; + while(pointer) { + if(pointer instanceof TranscludeWidget) { + depth--; + if(depth <= 0) { + break; + } + } + pointer = pointer.parentWidget; + } + // Process each parameter + if(pointer instanceof TranscludeWidget) { + // Get the value for each defined parameter + $tw.utils.each($tw.utils.getOrderedAttributesFromParseTreeNode(self.parseTreeNode),function(attr,index) { + var name = attr.name; + // If the attribute name starts with $$ then reduce to a single dollar + if(name.substr(0,2) === "$$") { + name = name.substr(1); + } + var value = pointer.getTransclusionParameter(name,index,self.getAttribute(attr.name,"")); + self.setVariable(name,value); + }); + // Assign any metaparameters + $tw.utils.each(pointer.getTransclusionMetaParameters(),function(getValue,name) { + var variableName = self.getAttribute("$" + name); + if(variableName) { + self.setVariable(variableName,getValue(name)); + } + }); + } + // Construct the child widgets + this.makeChildWidgets(); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +ParametersWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(Object.keys(changedAttributes).length) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.parameters = ParametersWidget; + +})(); diff --git a/core/modules/widgets/radio.js b/core/modules/widgets/radio.js index 363836227..aa7a32cf1 100644 --- a/core/modules/widgets/radio.js +++ b/core/modules/widgets/radio.js @@ -40,6 +40,10 @@ RadioWidget.prototype.render = function(parent,nextSibling) { ); this.inputDomNode = this.document.createElement("input"); this.inputDomNode.setAttribute("type","radio"); + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); if(isChecked) { this.inputDomNode.checked = true; } diff --git a/core/modules/widgets/range.js b/core/modules/widgets/range.js index 4dd55dc3c..db2699cc4 100644 --- a/core/modules/widgets/range.js +++ b/core/modules/widgets/range.js @@ -50,6 +50,10 @@ RangeWidget.prototype.render = function(parent,nextSibling) { this.inputDomNode.setAttribute("disabled",true); } this.inputDomNode.value = this.getValue(); + this.assignAttributes(this.inputDomNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ {name:"mousedown", handlerObject:this, handlerMethod:"handleMouseDownEvent"}, diff --git a/core/modules/widgets/reveal.js b/core/modules/widgets/reveal.js index 46e55e99e..3e3510f75 100755 --- a/core/modules/widgets/reveal.js +++ b/core/modules/widgets/reveal.js @@ -14,6 +14,8 @@ Reveal widget var Widget = require("$:/core/modules/widgets/widget.js").widget; +var Popup = require("$:/core/modules/utils/dom/popup.js"); + var RevealWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); }; @@ -94,6 +96,13 @@ RevealWidget.prototype.positionPopup = function(domNode) { left = Math.max(0,left); top = Math.max(0,top); } + if (this.popup.absolute) { + // Traverse the offsetParent chain and correct the offset to make it relative to the parent node. + for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) { + left -= offsetParentDomNode.offsetLeft; + top -= offsetParentDomNode.offsetTop; + } + } domNode.style.left = left + "px"; domNode.style.top = top + "px"; }; @@ -183,19 +192,11 @@ RevealWidget.prototype.compareStateText = function(state) { }; RevealWidget.prototype.readPopupState = function(state) { - var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/, - match = popupLocationRegExp.exec(state); + this.popup = Popup.parseCoordinates(state); // Check if the state matches the location regexp - if(match) { + if(this.popup) { // If so, we're open this.isOpen = true; - // Get the location - this.popup = { - left: parseFloat(match[1]), - top: parseFloat(match[2]), - width: parseFloat(match[3]), - height: parseFloat(match[4]) - }; } else { // If not, we're closed this.isOpen = false; diff --git a/core/modules/widgets/scrollable.js b/core/modules/widgets/scrollable.js index aadc040df..227c455c3 100644 --- a/core/modules/widgets/scrollable.js +++ b/core/modules/widgets/scrollable.js @@ -12,6 +12,8 @@ Scrollable widget /*global $tw: false */ "use strict"; +var DEBOUNCE_INTERVAL = 100; // Delay after last scroll event before updating the bound tiddler + var Widget = require("$:/core/modules/widgets/widget.js").widget; var ScrollableWidget = function(parseTreeNode,options) { @@ -119,8 +121,8 @@ ScrollableWidget.prototype.scrollIntoView = function(element,callback,options) { }; ScrollableWidget.prototype.scrollSelectorIntoView = function(baseElement,selector,callback,options) { - baseElement = baseElement || document.body; - var element = baseElement.querySelector(selector); + baseElement = baseElement || document; + var element = $tw.utils.querySelectorSafe(selector,baseElement); if(element) { this.scrollIntoView(element,callback,options); } @@ -171,6 +173,53 @@ ScrollableWidget.prototype.render = function(parent,nextSibling) { parent.insertBefore(this.outerDomNode,nextSibling); this.renderChildren(this.innerDomNode,null); this.domNodes.push(this.outerDomNode); + // If the scroll position is bound to a tiddler + if(this.scrollableBind) { + // After a delay for rendering, scroll to the bound position + this.updateScrollPositionFromBoundTiddler(); + // Set up event listener + this.currentListener = this.listenerFunction.bind(this); + this.outerDomNode.addEventListener("scroll", this.currentListener); + } +}; + +ScrollableWidget.prototype.listenerFunction = function(event) { + self = this; + clearTimeout(this.timeout); + this.timeout = setTimeout(function() { + var existingTiddler = self.wiki.getTiddler(self.scrollableBind), + newTiddlerFields = { + title: self.scrollableBind, + "scroll-left": self.outerDomNode.scrollLeft.toString(), + "scroll-top": self.outerDomNode.scrollTop.toString() + }; + if(!existingTiddler || (existingTiddler.fields["title"] !== newTiddlerFields["title"]) || (existingTiddler.fields["scroll-left"] !== newTiddlerFields["scroll-left"] || existingTiddler.fields["scroll-top"] !== newTiddlerFields["scroll-top"])) { + self.wiki.addTiddler(new $tw.Tiddler(existingTiddler,newTiddlerFields)); + } + }, DEBOUNCE_INTERVAL); +} + +ScrollableWidget.prototype.updateScrollPositionFromBoundTiddler = function() { + // Bail if we're running on the fakedom + if(!this.outerDomNode.scrollTo) { + return; + } + var tiddler = this.wiki.getTiddler(this.scrollableBind); + if(tiddler) { + var scrollLeftTo = this.outerDomNode.scrollLeft; + if(parseFloat(tiddler.fields["scroll-left"]).toString() === tiddler.fields["scroll-left"]) { + scrollLeftTo = parseFloat(tiddler.fields["scroll-left"]); + } + var scrollTopTo = this.outerDomNode.scrollTop; + if(parseFloat(tiddler.fields["scroll-top"]).toString() === tiddler.fields["scroll-top"]) { + scrollTopTo = parseFloat(tiddler.fields["scroll-top"]); + } + this.outerDomNode.scrollTo({ + top: scrollTopTo, + left: scrollLeftTo, + behavior: "instant" + }) + } }; /* @@ -178,6 +227,7 @@ Compute the internal state of the widget */ ScrollableWidget.prototype.execute = function() { // Get attributes + this.scrollableBind = this.getAttribute("bind"); this.fallthrough = this.getAttribute("fallthrough","yes"); this["class"] = this.getAttribute("class"); // Make child widgets @@ -193,7 +243,22 @@ ScrollableWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } - return this.refreshChildren(changedTiddlers); + // If the bound tiddler has changed, update the eventListener and update scroll position + if(changedAttributes["bind"]) { + if(this.currentListener) { + this.outerDomNode.removeEventListener("scroll", this.currentListener, false); + } + this.scrollableBind = this.getAttribute("bind"); + this.currentListener = this.listenerFunction.bind(this); + this.outerDomNode.addEventListener("scroll", this.currentListener); + } + // Refresh children + var result = this.refreshChildren(changedTiddlers); + // If the bound tiddler has changed, update scroll position + if(changedAttributes["bind"] || changedTiddlers[this.getAttribute("bind")]) { + this.updateScrollPositionFromBoundTiddler(); + } + return result; }; exports.scrollable = ScrollableWidget; diff --git a/core/modules/widgets/select.js b/core/modules/widgets/select.js index 8272a2783..2940e3be0 100644 --- a/core/modules/widgets/select.js +++ b/core/modules/widgets/select.js @@ -40,8 +40,35 @@ SelectWidget.prototype.render = function(parent,nextSibling) { this.parentDomNode = parent; this.computeAttributes(); this.execute(); - this.renderChildren(parent,nextSibling); + //Create element + var domNode = this.document.createElement("select"); + if(this.selectClass) { + domNode.className = this.selectClass; + } + // Assign data- attributes + this.assignAttributes(domNode,{ + sourcePrefix: "data-", + destPrefix: "data-" + }); + if(this.selectMultiple) { + domNode.setAttribute("multiple","multiple"); + } + if(this.selectSize) { + domNode.setAttribute("size",this.selectSize); + } + if(this.selectTabindex) { + domNode.setAttribute("tabindex",this.selectTabindex); + } + if(this.selectTooltip) { + domNode.setAttribute("title",this.selectTooltip); + } + this.parentDomNode.insertBefore(domNode,nextSibling); + this.renderChildren(domNode,null); + this.domNodes.push(domNode); this.setSelectValue(); + if(this.selectFocus == "yes") { + this.getSelectDomNode().focus(); + } $tw.utils.addEventListeners(this.getSelectDomNode(),[ {name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"} ]); @@ -110,7 +137,7 @@ SelectWidget.prototype.setSelectValue = function() { Get the DOM node of the select element */ SelectWidget.prototype.getSelectDomNode = function() { - return this.children[0].domNodes[0]; + return this.domNodes[0]; }; // Return an array of the selected opion values @@ -142,26 +169,11 @@ SelectWidget.prototype.execute = function() { this.selectDefault = this.getAttribute("default"); this.selectMultiple = this.getAttribute("multiple", false); this.selectSize = this.getAttribute("size"); + this.selectTabindex = this.getAttribute("tabindex"); this.selectTooltip = this.getAttribute("tooltip"); + this.selectFocus = this.getAttribute("focus"); // Make the child widgets - var selectNode = { - type: "element", - tag: "select", - children: this.parseTreeNode.children - }; - if(this.selectClass) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"class",this.selectClass); - } - if(this.selectMultiple) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"multiple","multiple"); - } - if(this.selectSize) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"size",this.selectSize); - } - if(this.selectTooltip) { - $tw.utils.addAttributeToParseTreeNode(selectNode,"title",this.selectTooltip); - } - this.makeChildWidgets([selectNode]); + this.makeChildWidgets(); }; /* @@ -170,17 +182,21 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of SelectWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // If we're using a different tiddler/field/index then completely refresh ourselves - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tooltip || changedAttributes.tabindex) { this.refreshSelf(); return true; - // If the target tiddler value has changed, just update setting and refresh the children } else { if(changedAttributes.class) { this.selectClass = this.getAttribute("class"); this.getSelectDomNode().setAttribute("class",this.selectClass); } - + this.assignAttributes(this.getSelectDomNode(),{ + changedAttributes: changedAttributes, + sourcePrefix: "data-", + destPrefix: "data-" + }); var childrenRefreshed = this.refreshChildren(changedTiddlers); + // If the target tiddler value has changed, just update setting and refresh the children if(changedTiddlers[this.selectTitle] || childrenRefreshed) { this.setSelectValue(); } diff --git a/core/modules/widgets/setvariable.js b/core/modules/widgets/setvariable.js index cc97067c7..f8e98f390 100755 --- a/core/modules/widgets/setvariable.js +++ b/core/modules/widgets/setvariable.js @@ -48,7 +48,17 @@ SetWidget.prototype.execute = function() { this.setValue = this.getAttribute("value"); this.setEmptyValue = this.getAttribute("emptyValue"); // Set context variable - this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,!!this.parseTreeNode.isMacroDefinition); + if(this.parseTreeNode.isMacroDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,true); + } else if(this.parseTreeNode.isFunctionDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isFunctionDefinition: true}); + } else if(this.parseTreeNode.isProcedureDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isProcedureDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace}); + } else if(this.parseTreeNode.isWidgetDefinition) { + this.setVariable(this.setName,this.getValue(),this.parseTreeNode.params,undefined,{isWidgetDefinition: true, configTrimWhiteSpace: this.parseTreeNode.configTrimWhiteSpace}); + } else { + this.setVariable(this.setName,this.getValue()); + } // Construct the child widgets this.makeChildWidgets(); }; diff --git a/core/modules/widgets/slot.js b/core/modules/widgets/slot.js new file mode 100644 index 000000000..eeaaedefe --- /dev/null +++ b/core/modules/widgets/slot.js @@ -0,0 +1,82 @@ +/*\ +title: $:/core/modules/widgets/slot.js +type: application/javascript +module-type: widget + +Widget for definition of slots within transcluded content. The values provided by the translusion are passed to the slot. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget, + TranscludeWidget = require("$:/core/modules/widgets/transclude.js").transclude; + +var SlotWidget = function(parseTreeNode,options) { + // Initialise + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +SlotWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +SlotWidget.prototype.render = function(parent,nextSibling) { + // Call the constructor + Widget.call(this); + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + this.renderChildren(parent,nextSibling); +}; + +/* +Compute the internal state of the widget +*/ +SlotWidget.prototype.execute = function() { + var self = this; + this.slotName = this.getAttribute("$name"); + this.slotDepth = parseInt(this.getAttribute("$depth","1"),10) || 1; + // Find the parent transclusions + var pointer = this.parentWidget, + depth = this.slotDepth; + while(pointer) { + if(pointer instanceof TranscludeWidget && pointer.hasVisibleSlots()) { + depth--; + if(depth <= 0) { + break; + } + } + pointer = pointer.parentWidget; + } + var parseTreeNodes = [{type: "text", attributes: {text: {type: "string", value: "Missing slot reference!"}}}]; + if(pointer instanceof TranscludeWidget) { + // Get the parse tree nodes comprising the slot contents + parseTreeNodes = pointer.getTransclusionSlotFill(this.slotName,this.parseTreeNode.children); + } + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Refresh the widget by ensuring our attributes are up to date +*/ +SlotWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes["$name"] || changedAttributes["$depth"]) { + this.refreshSelf(); + return true; + } + return this.refreshChildren(changedTiddlers); +}; + +exports.slot = SlotWidget; + +})(); diff --git a/core/modules/widgets/transclude.js b/core/modules/widgets/transclude.js index d7862d2eb..d30ab1fa7 100755 --- a/core/modules/widgets/transclude.js +++ b/core/modules/widgets/transclude.js @@ -37,48 +37,380 @@ TranscludeWidget.prototype.render = function(parent,nextSibling) { Compute the internal state of the widget */ TranscludeWidget.prototype.execute = function() { - // Get our parameters - this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); - this.transcludeSubTiddler = this.getAttribute("subtiddler"); - this.transcludeField = this.getAttribute("field"); - this.transcludeIndex = this.getAttribute("index"); - this.transcludeMode = this.getAttribute("mode"); - this.recursionMarker = this.getAttribute("recursionMarker","yes"); - // Parse the text reference + // Get our attributes, string parameters, and slot values into properties of the widget object + this.collectAttributes(); + this.collectStringParameters(); + this.collectSlotFillParameters(); + // Determine whether we're being used in inline or block mode var parseAsInline = !this.parseTreeNode.isBlock; if(this.transcludeMode === "inline") { parseAsInline = true; } else if(this.transcludeMode === "block") { parseAsInline = false; } - var parser = this.wiki.parseTextReference( + // Set 'thisTiddler' + this.setVariable("thisTiddler",this.transcludeTitle); + var parseTreeNodes, target; + // Process the transclusion according to the output type + switch(this.transcludeOutput || "text/html") { + case "text/html": + // Return the parse tree nodes of the target + target = this.parseTransclusionTarget(parseAsInline); + this.parseAsInline = target.parseAsInline; + parseTreeNodes = target.parseTreeNodes; + break; + case "text/raw": + // Just return the raw text + target = this.getTransclusionTarget(); + parseTreeNodes = [{type: "text", text: target.text}]; + break; + default: + // "text/plain" is the plain text result of wikifying the text + target = this.parseTransclusionTarget(parseAsInline); + var widgetNode = this.wiki.makeWidget(target.parser,{ + parentWidget: this, + document: $tw.fakeDocument + }); + var container = $tw.fakeDocument.createElement("div"); + widgetNode.render(container,null); + parseTreeNodes = [{type: "text", text: container.textContent}]; + break; + } + this.sourceText = target.text; + this.parserType = target.type; + // Set the legacy transclusion context variables only if we're not transcluding a variable + if(!this.transcludeVariable) { + var recursionMarker = this.makeRecursionMarker(); + this.setVariable("transclusion",recursionMarker); + } + // Construct the child widgets + this.makeChildWidgets(parseTreeNodes); +}; + +/* +Collect the attributes we need, in the process determining whether we're being used in legacy mode +*/ +TranscludeWidget.prototype.collectAttributes = function() { + var self = this; + // Detect legacy mode + this.legacyMode = true; + $tw.utils.each(this.attributes,function(value,name) { + if(name.charAt(0) === "$") { + self.legacyMode = false; + } + }); + // Get the attributes for the appropriate mode + if(this.legacyMode) { + this.transcludeTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); + this.transcludeSubTiddler = this.getAttribute("subtiddler"); + this.transcludeField = this.getAttribute("field"); + this.transcludeIndex = this.getAttribute("index"); + this.transcludeMode = this.getAttribute("mode"); + this.recursionMarker = this.getAttribute("recursionMarker","yes"); + } else { + this.transcludeVariable = this.getAttribute("$variable"); + this.transcludeVariableIsFunction = false; + this.transcludeType = this.getAttribute("$type"); + this.transcludeOutput = this.getAttribute("$output","text/html"); + this.transcludeTitle = this.getAttribute("$tiddler",this.getVariable("currentTiddler")); + this.transcludeSubTiddler = this.getAttribute("$subtiddler"); + this.transcludeField = this.getAttribute("$field"); + this.transcludeIndex = this.getAttribute("$index"); + this.transcludeMode = this.getAttribute("$mode"); + this.recursionMarker = this.getAttribute("$recursionMarker","yes"); + } +}; + +/* +Collect string parameters +*/ +TranscludeWidget.prototype.collectStringParameters = function() { + var self = this; + this.stringParametersByName = Object.create(null); + if(!this.legacyMode) { + $tw.utils.each(this.attributes,function(value,name) { + if(name.charAt(0) === "$") { + if(name.charAt(1) === "$") { + // Attributes starting $$ represent parameters starting with a single $ + name = name.slice(1); + } else { + // Attributes starting with a single $ are reserved for the widget + return; + } + } + self.stringParametersByName[name] = value; + }); + } +}; + +/* +Collect slot value parameters +*/ +TranscludeWidget.prototype.collectSlotFillParameters = function() { + var self = this; + this.slotFillParseTrees = Object.create(null); + if(this.legacyMode) { + this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children; + } else { + this.slotFillParseTrees["ts-raw"] = this.parseTreeNode.children; + var noFillWidgetsFound = true, + searchParseTreeNodes = function(nodes) { + $tw.utils.each(nodes,function(node) { + if(node.type === "fill") { + if(node.attributes["$name"] && node.attributes["$name"].type === "string") { + var slotValueName = node.attributes["$name"].value; + self.slotFillParseTrees[slotValueName] = node.children || []; + } + noFillWidgetsFound = false; + } else { + searchParseTreeNodes(node.children); + } + }); + }; + searchParseTreeNodes(this.parseTreeNode.children); + if(noFillWidgetsFound) { + this.slotFillParseTrees["ts-missing"] = this.parseTreeNode.children; + } + } +}; + +/* +Get transcluded details as an object {text:,type:} +*/ +TranscludeWidget.prototype.getTransclusionTarget = function() { + var self = this; + var text; + // Return the text and type of the target + if(this.hasAttribute("$variable")) { + if(this.transcludeVariable) { + // Transcluding a variable + var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}); + this.transcludeVariableIsFunction = variableInfo.srcVariable && variableInfo.srcVariable.isFunctionDefinition; + text = variableInfo.text; + this.transcludeFunctionResult = text; + return { + text: variableInfo.text, + type: this.transcludeType + }; + } + } else { + // Transcluding a text reference + var parserInfo = this.wiki.getTextReferenceParserInfo( + this.transcludeTitle, + this.transcludeField, + this.transcludeIndex, + { + subTiddler: this.transcludeSubTiddler, + defaultType: this.transcludeType + }); + return { + text: parserInfo.text, + type: parserInfo.type + }; + } +}; + +/* +Get transcluded parse tree nodes as an object {text:,type:,parseTreeNodes:,parseAsInline:} +*/ +TranscludeWidget.prototype.parseTransclusionTarget = function(parseAsInline) { + var self = this; + var parser; + // Get the parse tree + if(this.hasAttribute("$variable")) { + if(this.transcludeVariable) { + // Transcluding a variable + var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}), + srcVariable = variableInfo && variableInfo.srcVariable; + if(srcVariable && srcVariable.isFunctionDefinition) { + this.transcludeVariableIsFunction = true; + this.transcludeFunctionResult = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || ""; + } + if(variableInfo.text) { + if(srcVariable && srcVariable.isFunctionDefinition) { + parser = { + tree: [{ + type: "text", + text: this.transcludeFunctionResult + }], + source: this.transcludeFunctionResult, + type: "text/vnd.tiddlywiki" + }; + if(parseAsInline) { + parser.tree[0] = { + type: "text", + text: this.transcludeFunctionResult + }; + } else { + parser.tree[0] = { + type: "element", + tag: "p", + children: [{ + type: "text", + text: this.transcludeFunctionResult + }] + } + } + } else { + var cacheKey = (parseAsInline ? "inlineParser" : "blockParser") + (this.transcludeType || ""); + if(variableInfo.isCacheable && srcVariable[cacheKey]) { + parser = srcVariable[cacheKey]; + } else { + parser = this.wiki.parseText(this.transcludeType,variableInfo.text || "",{parseAsInline: parseAsInline, configTrimWhiteSpace: srcVariable && srcVariable.configTrimWhiteSpace}); + if(variableInfo.isCacheable) { + srcVariable[cacheKey] = parser; + } + } + } + if(parser) { + // Add parameters widget for procedures and custom widgets + if(srcVariable && (srcVariable.isProcedureDefinition || srcVariable.isWidgetDefinition)) { + parser = { + tree: [ + { + type: "parameters", + children: parser.tree + } + ], + source: parser.source, + type: parser.type + } + $tw.utils.each(srcVariable.params,function(param) { + var name = param.name; + // Parameter names starting with dollar must be escaped to double dollars + if(name.charAt(0) === "$") { + name = "$" + name; + } + $tw.utils.addAttributeToParseTreeNode(parser.tree[0],name,param["default"]) + }); + } else if(srcVariable && !srcVariable.isFunctionDefinition) { + // For macros and ordinary variables, wrap the parse tree in a vars widget assigning the parameters to variables named "__paramname__" + parser = { + tree: [ + { + type: "vars", + children: parser.tree + } + ], + source: parser.source, + type: parser.type + } + $tw.utils.each(variableInfo.params,function(param) { + $tw.utils.addAttributeToParseTreeNode(parser.tree[0],"__" + param.name + "__",param.value) + }); + } + } + } + } + } else { + // Transcluding a text reference + parser = this.wiki.parseTextReference( this.transcludeTitle, this.transcludeField, this.transcludeIndex, { parseAsInline: parseAsInline, - subTiddler: this.transcludeSubTiddler - }), - parseTreeNodes = parser ? parser.tree : this.parseTreeNode.children; - this.sourceText = parser ? parser.source : null; - this.parserType = parser? parser.type : null; - // Set context variables for recursion detection - var recursionMarker = this.makeRecursionMarker(); - if(this.recursionMarker === "yes") { - this.setVariable("transclusion",recursionMarker); + subTiddler: this.transcludeSubTiddler, + defaultType: this.transcludeType + }); } - // Check for recursion - if(parser) { - if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) { - parseTreeNodes = [{type: "error", attributes: { - "$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")} - }}]; + // Return the parse tree + return { + parser: parser, + parseTreeNodes: parser ? parser.tree : (this.slotFillParseTrees["ts-missing"] || []), + parseAsInline: parseAsInline, + text: parser && parser.source, + type: parser && parser.type + }; +}; + +/* +Fetch all the string parameters as an ordered array of {name:, value:} where the name is optional +*/ +TranscludeWidget.prototype.getOrderedTransclusionParameters = function() { + var result = []; + // Collect the parameters + for(var name in this.stringParametersByName) { + var value = this.stringParametersByName[name]; + result.push({name: name, value: value}); + } + // Sort numerical parameter names first + result.sort(function(a,b) { + var aIsNumeric = !isNaN(a.name), + bIsNumeric = !isNaN(b.name); + if(aIsNumeric && bIsNumeric) { + return a.name - b.name; + } else if(aIsNumeric) { + return -1; + } else if(bIsNumeric) { + return 1; + } else { + return a.name === b.name ? 0 : (a.name < b.name ? -1 : 1); + } + }); + // Remove names from numerical parameters + $tw.utils.each(result,function(param,index) { + if(!isNaN(param.name)) { + delete param.name; + } + }); + return result; +}; + +/* +Fetch the value of a parameter +*/ +TranscludeWidget.prototype.getTransclusionParameter = function(name,index,defaultValue) { + if(name in this.stringParametersByName) { + return this.stringParametersByName[name]; + } else { + var name = "" + index; + if(name in this.stringParametersByName) { + return this.stringParametersByName[name]; } } - // Construct the child widgets - this.makeChildWidgets(parseTreeNodes); + return defaultValue; }; +/* +Get one of the special parameters to be provided by the parameters widget +*/ +TranscludeWidget.prototype.getTransclusionMetaParameters = function() { + var self = this; + return { + "parseMode": function() { + return self.parseAsInline ? "inline" : "block"; + }, + "parseTreeNodes": function() { + return JSON.stringify(self.parseTreeNode.children || []); + }, + "slotFillParseTreeNodes": function() { + return JSON.stringify(self.slotFillParseTrees); + }, + "params": function() { + return JSON.stringify(self.stringParametersByName); + } + }; +}; + +/* +Fetch the value of a slot +*/ +TranscludeWidget.prototype.getTransclusionSlotFill = function(name,defaultParseTreeNodes) { + if(name && this.slotFillParseTrees[name] && this.slotFillParseTrees[name].length > 0) { + return this.slotFillParseTrees[name]; + } else { + return defaultParseTreeNodes || []; + } +}; + +/* +Return whether this transclusion should be visible to the slot widget +*/ +TranscludeWidget.prototype.hasVisibleSlots = function() { + return this.getAttribute("$fillignore","no") === "no"; +} + /* Compose a string comprising the title, field and/or index to identify this transclusion for recursion detection */ @@ -99,16 +431,24 @@ TranscludeWidget.prototype.makeRecursionMarker = function() { }; TranscludeWidget.prototype.parserNeedsRefresh = function() { + // Doesn't need to consider transcluded variables because a parent variable can't change once a widget has been created var parserInfo = this.wiki.getTextReferenceParserInfo(this.transcludeTitle,this.transcludeField,this.transcludeIndex,{subTiddler:this.transcludeSubTiddler}); return (this.sourceText === undefined || parserInfo.sourceText !== this.sourceText || parserInfo.parserType !== this.parserType) }; +TranscludeWidget.prototype.functionNeedsRefresh = function() { + var oldResult = this.transcludeFunctionResult; + var variableInfo = this.getVariableInfo(this.transcludeVariable,{params: this.getOrderedTransclusionParameters()}); + var newResult = (variableInfo.resultList ? variableInfo.resultList[0] : variableInfo.text) || ""; + return oldResult !== newResult; +} + /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ TranscludeWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(($tw.utils.count(changedAttributes) > 0) || (changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { + if(($tw.utils.count(changedAttributes) > 0) || (this.transcludeVariableIsFunction && this.functionNeedsRefresh()) || (!this.transcludeVariable && changedTiddlers[this.transcludeTitle] && this.parserNeedsRefresh())) { this.refreshSelf(); return true; } else { diff --git a/core/modules/widgets/view.js b/core/modules/widgets/view.js index 6effc8939..070836bff 100755 --- a/core/modules/widgets/view.js +++ b/core/modules/widgets/view.js @@ -168,11 +168,11 @@ ViewWidget.prototype.getValueAsHtmlTextEncoded = function() { }; ViewWidget.prototype.getValueAsUrlEncoded = function() { - return encodeURIComponent(this.getValueAsText()); + return $tw.utils.encodeURIComponentExtended(this.getValueAsText()); }; ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() { - return encodeURIComponent(encodeURIComponent(this.getValueAsText())); + return $tw.utils.encodeURIComponentExtended($tw.utils.encodeURIComponentExtended(this.getValueAsText())); }; ViewWidget.prototype.getValueAsDate = function(format) { diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 60f55e8bb..ea300ca0e 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -41,10 +41,7 @@ Widget.prototype.initialise = function(parseTreeNode,options) { this.parseTreeNode = parseTreeNode; this.wiki = options.wiki; this.parentWidget = options.parentWidget; - this.variables = Object.create(null); - if(this.parentWidget) { - Object.setPrototypeOf(this.variables,this.parentWidget.variables); - } + this.variables = Object.create(this.parentWidget ? this.parentWidget.variables : null); this.document = options.document; this.attributes = {}; this.children = []; @@ -92,9 +89,22 @@ name: name of the variable value: value of the variable params: array of {name:, default:} for each parameter isMacroDefinition: true if the variable is set via a \define macro pragma (and hence should have variable substitution performed) +options includes: + isProcedureDefinition: true if the variable is set via a \procedure pragma (and hence should not have variable substitution performed) + isFunctionDefinition: true if the variable is set via a \function pragma (and hence should not have variable substitution performed) + isWidgetDefinition: true if the variable is set via a \widget pragma (and hence should not have variable substitution performed) */ -Widget.prototype.setVariable = function(name,value,params,isMacroDefinition) { - this.variables[name] = {value: value, params: params, isMacroDefinition: !!isMacroDefinition}; +Widget.prototype.setVariable = function(name,value,params,isMacroDefinition,options) { + options = options || {}; + this.variables[name] = { + value: value, + params: params, + isMacroDefinition: !!isMacroDefinition, + isFunctionDefinition: !!options.isFunctionDefinition, + isProcedureDefinition: !!options.isProcedureDefinition, + isWidgetDefinition: !!options.isWidgetDefinition, + configTrimWhiteSpace: !!options.configTrimWhiteSpace + }; }; /* @@ -102,42 +112,77 @@ Get the prevailing value of a context variable name: name of variable options: see below Options include + params: array of {name:, value:} for each parameter defaultValue: default value if the variable is not defined +source: optional source iterator for evaluating function invocations +allowSelfAssigned: if true, includes the current widget in the context chain instead of just the parent Returns an object with the following fields: -params: array of {name:,value:} of parameters passed to wikitext variables +params: array of {name:,value:} or {value:} of parameters to be applied text: text of variable, with parameters properly substituted +resultList: result of variable evaluation as an array +srcVariable: reference to the object defining the variable */ Widget.prototype.getVariableInfo = function(name,options) { options = options || {}; - var actualParams = options.params || [], - parentWidget = this.parentWidget; + var self = this, + actualParams = options.params || [], + variable; + if(options.allowSelfAssigned) { + variable = this.variables[name]; + } else { + variable = this.parentWidget && this.parentWidget.variables[name]; + } // Check for the variable defined in the parent widget (or an ancestor in the prototype chain) - if(parentWidget && name in parentWidget.variables) { - var variable = parentWidget.variables[name], - originalValue = variable.value, + if(variable) { + var originalValue = variable.value, value = originalValue, - params = this.resolveVariableParameters(variable.params,actualParams); - // Substitute any parameters specified in the definition - $tw.utils.each(params,function(param) { - value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value); - }); - // Only substitute variable references if this variable was defined with the \define pragma + params = [], + resultList = [value]; + // Only substitute parameter and variable references if this variable was defined with the \define pragma if(variable.isMacroDefinition) { - value = this.substituteVariableReferences(value,options); + params = self.resolveVariableParameters(variable.params,actualParams); + // Substitute any parameters specified in the definition + $tw.utils.each(params,function(param) { + value = $tw.utils.replaceString(value,new RegExp("\\$" + $tw.utils.escapeRegExp(param.name) + "\\$","mg"),param.value); + }); + value = self.substituteVariableReferences(value,options); + resultList = [value]; + } else if(variable.isFunctionDefinition) { + // Function evaluations + params = self.resolveVariableParameters(variable.params,actualParams); + var variables = options.variables || Object.create(null); + // Apply default parameter values + $tw.utils.each(variable.params,function(param,index) { + if(param["default"]) { + variables[param.name] = param["default"]; + } + }); + // Parameters are an array of {value:} or {name:, value:} pairs + $tw.utils.each(params,function(param) { + variables[param.name] = param.value; + }); + resultList = this.wiki.filterTiddlers(value,this.makeFakeWidgetWithVariables(variables),options.source); + value = resultList[0] || ""; } return { text: value, params: params, + resultList: resultList, srcVariable: variable, isCacheable: originalValue === value }; } // If the variable doesn't exist in the parent widget then look for a macro module + var text = this.evaluateMacroModule(name,actualParams); + if(text === undefined) { + text = options.defaultValue; + } return { - text: this.evaluateMacroModule(name,actualParams,options.defaultValue) + text: text, + resultList: [text] }; }; @@ -148,6 +193,11 @@ Widget.prototype.getVariable = function(name,options) { return this.getVariableInfo(name,options).text; }; +/* +Maps actual parameters onto formal parameters, returning an array of {name:,value:} objects +formalParams - Array of {name:,default:} (default value is optional) +actualParams - Array of string values or {name:,value:} (name is optional) +*/ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) { formalParams = formalParams || []; actualParams = actualParams || []; @@ -160,7 +210,7 @@ Widget.prototype.resolveVariableParameters = function(formalParams,actualParams) paramInfo = formalParams[p]; paramValue = undefined; for(var m=0; m 6) { + domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value; + return; + } + // Check if the sourcePrefix is a match + if(name.substr(0,sourcePrefix.length) === sourcePrefix) { + name = destPrefix + name.substr(sourcePrefix.length); + } else { + value = undefined; + } // Check for excluded attribute names - if(options.excludeEventAttributes && name.substr(0,2) === "on") { + if(options.excludeEventAttributes && name.substr(0,2).toLowerCase() === EVENT_ATTRIBUTE_PREFIX) { value = undefined; } if(value !== undefined) { @@ -337,26 +450,24 @@ Widget.prototype.assignAttributes = function(domNode,options) { namespace = "http://www.w3.org/1999/xlink"; name = name.substr(6); } - // Handle styles - if(name.substr(0,6) === "style." && name.length > 6) { - domNode.style[$tw.utils.unHyphenateCss(name.substr(6))] = value; - } else { - // Setting certain attributes can cause a DOM error (eg xmlns on the svg element) - try { - domNode.setAttributeNS(namespace,name,value); - } catch(e) { - } + // Setting certain attributes can cause a DOM error (eg xmlns on the svg element) + try { + domNode.setAttributeNS(namespace,name,value); + } catch(e) { } } - } - // Not all parse tree nodes have the orderedAttributes property + }; + // If the parse tree node has the orderedAttributes property then use that order if(this.parseTreeNode.orderedAttributes) { $tw.utils.each(this.parseTreeNode.orderedAttributes,function(attribute,index) { - assignAttribute(attribute.name,self.attributes[attribute.name]); - }); + if(attribute.name in changedAttributes) { + assignAttribute(attribute.name,self.getAttribute(attribute.name)); + } + }); + // Otherwise update each changed attribute irrespective of order } else { - $tw.utils.each(Object.keys(self.attributes).sort(),function(name) { - assignAttribute(name,self.attributes[name]); + $tw.utils.each(changedAttributes,function(value,name) { + assignAttribute(name,self.getAttribute(name)); }); } }; @@ -413,7 +524,34 @@ options include: variables: optional hashmap of variables to wrap around the widget */ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { + var self = this; options = options || {}; + // Check whether this node type is defined by a custom widget definition + var variableDefinitionName = "$" + parseTreeNode.type; + if(this.variables[variableDefinitionName]) { + var isOverrideable = function() { + // Widget is overrideable if its name contains a period, or if it is an existing JS widget and we're not in safe mode + return parseTreeNode.type.indexOf(".") !== -1 || (!!self.widgetClasses[parseTreeNode.type] && !$tw.safeMode); + }; + if(!parseTreeNode.isNotRemappable && isOverrideable()) { + var variableInfo = this.getVariableInfo(variableDefinitionName,{allowSelfAssigned: true}); + if(variableInfo && variableInfo.srcVariable && variableInfo.srcVariable.value && variableInfo.srcVariable.isWidgetDefinition) { + var newParseTreeNode = { + type: "transclude", + children: parseTreeNode.children, + isBlock: parseTreeNode.isBlock + }; + $tw.utils.addAttributeToParseTreeNode(newParseTreeNode,"$variable",variableDefinitionName); + $tw.utils.each(parseTreeNode.attributes,function(attr,name) { + // If the attribute starts with a dollar then add an extra dollar so that it doesn't clash with the $xxx attributes of transclude + name = name.charAt(0) === "$" ? "$" + name : name; + $tw.utils.addAttributeToParseTreeNode(newParseTreeNode,$tw.utils.extend({},attr,{name: name})); + }); + parseTreeNode = newParseTreeNode; + } + } + } + // Get the widget class for this node type var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; @@ -675,6 +813,20 @@ Widget.prototype.allowActionPropagation = function() { return true; }; +/* +Evaluate a variable with parameters. This is a static convenience method that attempts to evaluate a variable as a function, returning an array of strings +*/ +Widget.evaluateVariable = function(widget,name,options) { + var result; + if(widget.getVariableInfo) { + var variableInfo = widget.getVariableInfo(name,options); + result = variableInfo.resultList || [variableInfo.text]; + } else { + result = [widget.getVariable(name)]; + } + return result; +}; + exports.widget = Widget; })(); diff --git a/core/modules/wiki.js b/core/modules/wiki.js index c3f272348..430c46466 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -988,7 +988,8 @@ exports.parseText = function(type,text,options) { return new Parser(type,text,{ parseAsInline: options.parseAsInline, wiki: this, - _canonical_uri: options._canonical_uri + _canonical_uri: options._canonical_uri, + configTrimWhiteSpace: options.configTrimWhiteSpace }); }; @@ -1028,10 +1029,11 @@ exports.parseTextReference = function(title,field,index,options) { }; exports.getTextReferenceParserInfo = function(title,field,index,options) { - var tiddler, + var defaultType = options.defaultType || "text/vnd.tiddlywiki", + tiddler, parserInfo = { sourceText : null, - parserType : "text/vnd.tiddlywiki" + parserType : defaultType }; if(options.subTiddler) { tiddler = this.getSubTiddler(title,options.subTiddler); @@ -1061,6 +1063,34 @@ exports.getTextReferenceParserInfo = function(title,field,index,options) { return parserInfo; } +/* +Parse a block of text of a specified MIME type + text: text on which to perform substitutions + widget + options: see below +Options include: + substitutions: an optional array of substitutions +*/ +exports.getSubstitutedText = function(text,widget,options) { + options = options || {}; + text = text || ""; + var self = this, + substitutions = options.substitutions || [], + output; + // Evaluate embedded filters and substitute with first result + output = text.replace(/\$\{([\S\s]+?)\}\$/g, function(match,filter) { + return self.filterTiddlers(filter,widget)[0] || ""; + }); + // Process any substitutions provided in options + $tw.utils.each(substitutions,function(substitute) { + output = $tw.utils.replaceString(output,new RegExp("\\$" + $tw.utils.escapeRegExp(substitute.name) + "\\$","mg"),substitute.value); + }); + // Substitute any variable references with their values + return output.replace(/\$\(([^\)\$]+)\)\$/g, function(match,varname) { + return widget.getVariable(varname,{defaultValue: ""}) + }); +}; + /* Make a widget tree for a parse tree parser: parser object @@ -1077,19 +1107,20 @@ exports.makeWidget = function(parser,options) { children: [] }, currWidgetNode = widgetNode; - // Create set variable widgets for each variable - $tw.utils.each(options.variables,function(value,name) { - var setVariableWidget = { - type: "set", + // Create let variable widget for variables + if($tw.utils.count(options.variables) > 0) { + var letVariableWidget = { + type: "let", attributes: { - name: {type: "string", value: name}, - value: {type: "string", value: value} }, children: [] }; - currWidgetNode.children = [setVariableWidget]; - currWidgetNode = setVariableWidget; - }); + $tw.utils.each(options.variables,function(value,name) { + $tw.utils.addAttributeToParseTreeNode(letVariableWidget,name,"" + value); + }); + currWidgetNode.children = [letVariableWidget]; + currWidgetNode = letVariableWidget; + } // Add in the supplied parse tree nodes currWidgetNode.children = parser ? parser.tree : []; // Create the widget @@ -1146,7 +1177,7 @@ exports.makeTranscludeWidget = function(title,options) { if(options.importVariables) { parseTreeImportVariables.attributes.filter.value = options.importVariables; } else if(options.importPageMacros) { - parseTreeImportVariables.attributes.filter.value = "[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]"; + parseTreeImportVariables.attributes.filter.value = this.getTiddlerText("$:/core/config/GlobalImportFilter"); } parseTreeDiv.tree[0].children.push(parseTreeImportVariables); parseTreeImportVariables.children.push(parseTreeTransclude); @@ -1256,7 +1287,7 @@ exports.search = function(text,options) { console.log("Regexp error parsing /(" + text + ")/" + flags + ": ",e); } } else if(options.some) { - terms = text.trim().split(/ +/); + terms = text.trim().split(/[^\S\xA0]+/); if(terms.length === 1 && terms[0] === "") { searchTermsRegExps = null; } else { @@ -1267,7 +1298,7 @@ exports.search = function(text,options) { searchTermsRegExps.push(new RegExp("(" + regExpStr + ")",flags)); } } else { // default: words - terms = text.split(/ +/); + terms = text.split(/[^\S\xA0]+/); if(terms.length === 1 && terms[0] === "") { searchTermsRegExps = null; } else { @@ -1412,6 +1443,14 @@ exports.checkTiddlerText = function(title,targetText,options) { return text === targetText; } +/* +Execute an action string without an associated context widget +*/ +exports.invokeActionString = function(actions,event,variables,options) { + var widget = this.makeWidget(null,{parentWidget: options.parentWidget}); + widget.invokeActionString(actions,null,event,variables); +}; + /* Read an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read */ diff --git a/core/palettes/Vanilla.tid b/core/palettes/Vanilla.tid index d84b4ec83..4c660e912 100644 --- a/core/palettes/Vanilla.tid +++ b/core/palettes/Vanilla.tid @@ -54,6 +54,7 @@ modal-footer-background: #f5f5f5 modal-footer-border: #dddddd modal-header-border: #eeeeee muted-foreground: #bbb +network-activity-foreground: #448844 notification-background: #ffffdd notification-border: #999999 page-background: #f4f4f4 diff --git a/core/templates/exporters/StaticRiver.tid b/core/templates/exporters/StaticRiver.tid index 4583bc1ce..3b70c9d11 100644 --- a/core/templates/exporters/StaticRiver.tid +++ b/core/templates/exporters/StaticRiver.tid @@ -3,6 +3,7 @@ tags: $:/tags/Exporter description: {{$:/language/Exporters/StaticRiver}} extension: .html +\define tv-config-static() yes \define tv-wikilink-template() #$uri_encoded$ \define tv-config-toolbar-icons() no \define tv-config-toolbar-text() no @@ -14,6 +15,7 @@ extension: .html + {{$:/core/wiki/title}} diff --git a/core/templates/exporters/StaticRiverContent.tid b/core/templates/exporters/StaticRiverContent.tid index 0b04549f9..3d42be807 100644 --- a/core/templates/exporters/StaticRiverContent.tid +++ b/core/templates/exporters/StaticRiverContent.tid @@ -3,5 +3,5 @@ title: $:/core/templates/exporters/StaticRiver/Content \define renderContent() {{{ $(exportFilter)$ ||$:/core/templates/static-tiddler}}} \end -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] <> diff --git a/core/templates/exporters/TidFile.tid b/core/templates/exporters/TidFile.tid index 1dbd3503b..7b0bb2d78 100644 --- a/core/templates/exporters/TidFile.tid +++ b/core/templates/exporters/TidFile.tid @@ -7,5 +7,5 @@ condition: [compare:lte[1]] \define renderContent() {{{ $(exportFilter)$ +[limit[1]] ||$:/core/templates/tid-tiddler}}} \end -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] <> \ No newline at end of file diff --git a/core/templates/external-js/save-all-external-js.tid b/core/templates/external-js/save-all-external-js.tid index a41cc0682..ff5bbc851 100644 --- a/core/templates/external-js/save-all-external-js.tid +++ b/core/templates/external-js/save-all-external-js.tid @@ -1,8 +1,14 @@ title: $:/core/save/all-external-js -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\whitespace trim +\import [subfilter{$:/core/config/GlobalImportFilter}] \define saveTiddlerFilter() [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ \end -\define coreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js -{{$:/core/templates/tiddlywiki5-external-js.html}} + + +\define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js + +<$let coreURL={{{ [[coreURL]is[variable]thenelse] }}}> + {{$:/core/templates/tiddlywiki5-external-js.html}} + diff --git a/core/templates/external-js/save-offline-external-js.tid b/core/templates/external-js/save-offline-external-js.tid index 7175f7eea..564a34948 100644 --- a/core/templates/external-js/save-offline-external-js.tid +++ b/core/templates/external-js/save-offline-external-js.tid @@ -1,8 +1,11 @@ title: $:/core/save/offline-external-js -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\whitespace trim +\import [subfilter{$:/core/config/GlobalImportFilter}] \define saveTiddlerFilter() [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ \end -\define coreURL() tiddlywikicore-$(version)$.js -{{$:/core/templates/tiddlywiki5-external-js.html}} +\define defaultCoreURL() tiddlywikicore-$(version)$.js +<$let coreURL={{{ [[coreURL]is[variable]thenelse] }}}> + {{$:/core/templates/tiddlywiki5-external-js.html}} + diff --git a/core/templates/external-js/tiddlywiki.js.load.tid b/core/templates/external-js/tiddlywiki.js.load.tid new file mode 100644 index 000000000..496d6ed04 --- /dev/null +++ b/core/templates/external-js/tiddlywiki.js.load.tid @@ -0,0 +1,3 @@ +title: $:/core/templates/tiddlywiki.js/load-tiddler + +_load(window,<$macrocall $name="jsontiddler" $output="text/raw"/>); \ No newline at end of file diff --git a/core/templates/external-js/tiddlywiki.js.tid b/core/templates/external-js/tiddlywiki.js.tid index a8170663f..f962569a2 100644 --- a/core/templates/external-js/tiddlywiki.js.tid +++ b/core/templates/external-js/tiddlywiki.js.tid @@ -1,15 +1,48 @@ + title: $:/core/templates/tiddlywiki5.js \rules only filteredtranscludeinline transcludeinline codeinline -/* -{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}} -`*/ -` -{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/plain-text-tiddler}}} - -{{ $:/boot/bootprefix.js ||$:/core/templates/plain-text-tiddler}} - -{{$:/core/templates/tiddlywiki5.js/tiddlers}} - -{{ $:/boot/boot.js ||$:/core/templates/plain-text-tiddler}} +`/* +`{{ $:/core/copyright.txt ||$:/core/templates/plain-text-tiddler}}` +*/ + +$tw = (typeof $tw === 'undefined') ? Object.create(null) : $tw; + +$tw.preloadTiddlers = $tw.preloadTiddlers || []; + +_load = function(window,tiddler) { + "use strict"; + var f; + $tw.preloadTiddlers.push(tiddler); + if(tiddler.library === "yes") { + var module = { exports:{} }; + var moduleName = function moduleName(path) { + var word = path.split("/").pop(); + word = word.substring(0,word.indexOf(".")) || word; + return word; + } + f = new Function("module",tiddler.text); + f(module); + window[moduleName(tiddler.title)] = module.exports; + } else { + f = new Function("window",tiddler.text); + f(window); + } +} + +/* ~~ Library modules ~~ */ + +`{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/tiddlywiki.js/load-tiddler}}}` + +/* ~~ Boot kernel prologue ~~ */ + +`{{ $:/boot/bootprefix.js ||$:/core/templates/tiddlywiki.js/load-tiddler}}` + +/* ~~ Core tiddlers ~~ */ + +`{{$:/core/templates/tiddlywiki5.js/tiddlers}}` + +/* ~~ Boot kernel ~~ */ + +`{{ $:/boot/boot.js ||$:/core/templates/tiddlywiki.js/load-tiddler}}` diff --git a/core/templates/external-js/tiddlywiki5-external-js.html.tid b/core/templates/external-js/tiddlywiki5-external-js.html.tid index 6a5c4c1bb..b161584d7 100644 --- a/core/templates/external-js/tiddlywiki5-external-js.html.tid +++ b/core/templates/external-js/tiddlywiki5-external-js.html.tid @@ -1,48 +1,50 @@ title: $:/core/templates/tiddlywiki5-external-js.html -\rules only filteredtranscludeinline transcludeinline - -{{$:/core/templates/MOTW.html}} +<$set name="saveTiddlerAndShadowsFilter" filter="[subfilter] [subfilterplugintiddlers[]]"> +` +`{{$:/core/templates/MOTW.html}}` -{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}} +`{{{ [enlisttag[$:/tags/RawMarkupWikified/TopHead]] ||$:/core/templates/raw-static-tiddler}}}` - + - + -{{$:/core/wiki/title}} +`{{$:/core/wiki/title}}` -{{{ [all[shadows+tiddlers]tag[$:/core/wiki/rawmarkup]] [all[shadows+tiddlers]tag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}} -{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}} +`{{{ [enlisttag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}` +`{{{ [enlisttag[$:/tags/RawMarkup]] ||$:/core/templates/plain-text-tiddler}}}` +`{{{ [enlisttag[$:/tags/RawMarkupWikified]] ||$:/core/templates/raw-static-tiddler}}}` -{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}} +`{{{ [enlisttag[$:/tags/RawMarkupWikified/TopBody]] ||$:/core/templates/raw-static-tiddler}}}`
-{{$:/boot/boot.css||$:/core/templates/css-tiddler}} +`{{$:/boot/boot.css||$:/core/templates/css-tiddler}}`
-{{$:/core/templates/store.area.template.html}} +`{{$:/core/templates/store.area.template.html}}` -{{{ [all[shadows+tiddlers]tag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}} +`{{{ [enlisttag[$:/tags/RawMarkupWikified/BottomBody]] ||$:/core/templates/raw-static-tiddler}}}` + + - - - +` + \ No newline at end of file diff --git a/core/templates/html-json-skinny-tiddler.tid b/core/templates/html-json-skinny-tiddler.tid index 1e3c032f3..6402bcee5 100644 --- a/core/templates/html-json-skinny-tiddler.tid +++ b/core/templates/html-json-skinny-tiddler.tid @@ -1,4 +1,3 @@ title: $:/core/templates/html-json-skinny-tiddler -<$list filter="[compare:number:gteq[1]] ~[!match[1]]">`,`<$text text=<>/> -<$jsontiddler tiddler=<> exclude="text" escapeUnsafeScriptChars="yes"/> +<$text text=<>/><$jsontiddler tiddler=<> exclude="text" escapeUnsafeScriptChars="yes"/> diff --git a/core/templates/html-json-tiddler.tid b/core/templates/html-json-tiddler.tid index 6b62b4ac9..2e12290a7 100644 --- a/core/templates/html-json-tiddler.tid +++ b/core/templates/html-json-tiddler.tid @@ -1,3 +1,3 @@ title: $:/core/templates/html-json-tiddler -<$list filter="[!match[1]]">`,`<$text text=<>/><$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes"/> \ No newline at end of file +<$jsontiddler tiddler=<> escapeUnsafeScriptChars="yes"/> \ No newline at end of file diff --git a/core/templates/save-all.tid b/core/templates/save-all.tid index b298ad49f..d7473ba5b 100644 --- a/core/templates/save-all.tid +++ b/core/templates/save-all.tid @@ -1,6 +1,6 @@ title: $:/core/save/all -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] \define saveTiddlerFilter() [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ \end diff --git a/core/templates/server/static.tiddler.html.tid b/core/templates/server/static.tiddler.html.tid index 1a803bd86..6c9fd80a5 100644 --- a/core/templates/server/static.tiddler.html.tid +++ b/core/templates/server/static.tiddler.html.tid @@ -1,8 +1,9 @@ title: $:/core/templates/server/static.tiddler.html \whitespace trim +\define tv-config-static() yes \define tv-wikilink-template() $uri_encoded$ -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] diff --git a/core/templates/single.tiddler.window.tid b/core/templates/single.tiddler.window.tid index 0d14509e5..aa5175c01 100644 --- a/core/templates/single.tiddler.window.tid +++ b/core/templates/single.tiddler.window.tid @@ -4,7 +4,7 @@ title: $:/core/templates/single.tiddler.window \define containerClasses() tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$ \end -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] <$vars tv-config-toolbar-icons={{$:/config/Toolbar/Icons}} diff --git a/core/templates/static.template.html.tid b/core/templates/static.template.html.tid index 5da5fb752..8b6482846 100644 --- a/core/templates/static.template.html.tid +++ b/core/templates/static.template.html.tid @@ -1,6 +1,7 @@ title: $:/core/templates/static.template.html type: text/vnd.tiddlywiki-html +\define tv-config-static() yes \define tv-wikilink-template() static/$uri_doubleencoded$.html \define tv-config-toolbar-icons() no \define tv-config-toolbar-text() no diff --git a/core/templates/static.tiddler.html.tid b/core/templates/static.tiddler.html.tid index a4537305a..a3297ee78 100644 --- a/core/templates/static.tiddler.html.tid +++ b/core/templates/static.tiddler.html.tid @@ -1,10 +1,11 @@ title: $:/core/templates/static.tiddler.html \define tv-wikilink-template() $uri_doubleencoded$.html +\define tv-config-static() yes \define tv-config-toolbar-icons() no \define tv-config-toolbar-text() no \define tv-config-toolbar-class() tc-btn-invisible -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] ` diff --git a/core/templates/store.area.template.html.tid b/core/templates/store.area.template.html.tid index 84dd0c432..2dc115266 100644 --- a/core/templates/store.area.template.html.tid +++ b/core/templates/store.area.template.html.tid @@ -6,14 +6,12 @@ title: $:/core/templates/store.area.template.html <$list filter="[[storeAreaFormat]is[variable]getvariable[]else[json]match[json]]"> `` `` @@ -22,8 +20,8 @@ title: $:/core/templates/store.area.template.html <$reveal type="nomatch" state="$:/isEncrypted" text="yes"> `` diff --git a/core/ui/AdvancedSearch/FilterButtons/dropdown.tid b/core/ui/AdvancedSearch/FilterButtons/dropdown.tid index b1d400aeb..44878af77 100644 --- a/core/ui/AdvancedSearch/FilterButtons/dropdown.tid +++ b/core/ui/AdvancedSearch/FilterButtons/dropdown.tid @@ -14,7 +14,7 @@ tags: $:/tags/AdvancedSearch/FilterButton <$linkcatcher actions="<$action-setfield $tiddler='$:/temp/advancedsearch' text=<>/><$action-setfield $tiddler='$:/temp/advancedsearch/input' text=<>/><$action-setfield $tiddler='$:/temp/advancedsearch/refresh' text='yes'/><$action-sendmessage $message='tm-focus-selector' $param='.tc-advanced-search input' />">
-<$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]]"> +<$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]!is[draft]]"> <$link to={{!!filter}}><$let tv-wikilinks="no"><$transclude field="description"/>
diff --git a/core/ui/AdvancedSearch/Standard.tid b/core/ui/AdvancedSearch/Standard.tid index 0690130e4..41ddcf4bc 100644 --- a/core/ui/AdvancedSearch/Standard.tid +++ b/core/ui/AdvancedSearch/Standard.tid @@ -54,7 +54,7 @@ caption: {{$:/language/Search/Standard/Caption}} variable="listItem"> <$vars userInput={{{ [[$:/temp/advancedsearch]get[text]] }}} - configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} + configTiddler={{{ [[$:/state/advancedsearch/standard/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} searchListState="$:/temp/advancedsearch/selected-item"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/SearchResults]!has[draft.of]butfirst[]limit[1]]" diff --git a/core/ui/AlertTemplate.tid b/core/ui/AlertTemplate.tid index ae15818a0..d67586b8d 100644 --- a/core/ui/AlertTemplate.tid +++ b/core/ui/AlertTemplate.tid @@ -1,3 +1,4 @@ +code-body: yes title: $:/core/ui/AlertTemplate \whitespace trim diff --git a/core/ui/Components/VisibleTransclude.tid b/core/ui/Components/VisibleTransclude.tid new file mode 100644 index 000000000..27fdff998 --- /dev/null +++ b/core/ui/Components/VisibleTransclude.tid @@ -0,0 +1,48 @@ +title: $:/core/ui/VisibleTransclude + + +\widget $transclude() + +<$parameters tiddler="" $$tiddler="" mode="" $$mode="" $parseMode="@parseMode" $params="@params"> + + <$let + mode={{{ [[$mode]is[variable]then<$mode>!is[blank]] :else[[mode]is[variable]then!is[blank]] :else[<@parseMode>] }}} + outputTag={{{ [match[inline]then[span]else[div]] }}} + outputColour={{{ [match[inline]then[green]else[red]] }}} + > + + <$genesis $type=<> style="color:white;padding:4px;" style.background=<>> + <$genesis $type=<> style="display: inline-block;"> +
+ + <$list filter="[<@params>jsonindexes[]]" emptyMessage="(none)"> +
+ <$text text=<>/><$text text=": "/><$text text={{{ [<@params>jsonget] }}}/> +
+ +
+ + <$genesis $type=<> style="background:white;color:black;padding:4px;"> + + <$list filter="[<@params>jsonindexes[]] :filter[prefix[$]] +[limit[1]]" variable="ignore" emptyMessage=""" + + <$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget]" recursionMarker="no" mode=<> $$fillignore="yes"> + + <$slot $name="ts-raw"/> + + """> + + <$genesis $type="$transclude" $remappable="no" $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsonget]" $$recursionMarker="no" $$mode=<> $$fillignore="yes"> + + <$slot $name="ts-raw"/> + + + + + + +\end diff --git a/core/ui/ControlPanel/Basics.tid b/core/ui/ControlPanel/Basics.tid index 46df7e77c..b2ef2832a 100644 --- a/core/ui/ControlPanel/Basics.tid +++ b/core/ui/ControlPanel/Basics.tid @@ -20,15 +20,16 @@ caption: {{$:/language/ControlPanel/Basics/Caption}} \end \whitespace trim +|tc-max-width tc-edit-max-width|k |<> |''<>'' | |<$link to="$:/SiteTitle"><> |<$edit-text tiddler="$:/SiteTitle" default="" tag="input"/> | |<$link to="$:/SiteSubtitle"><> |<$edit-text tiddler="$:/SiteSubtitle" default="" tag="input"/> | |<$link to="$:/status/UserName"><> |<$edit-text tiddler="$:/status/UserName" default="" tag="input"/> | |<$link to="$:/config/AnimationDuration"><> |<$edit-text tiddler="$:/config/AnimationDuration" default="" tag="input"/> | -|<$link to="$:/DefaultTiddlers"><> |<>
<$edit tag="textarea" tiddler="$:/DefaultTiddlers" class="tc-edit-texteditor"/>
//<>// | +|<$link to="$:/DefaultTiddlers"><> |<>
<$edit class="tc-edit-texteditor" tiddler="$:/DefaultTiddlers" autoHeight="yes"/>
//<>// | |<$link to="$:/language/DefaultNewTiddlerTitle"><> |<$edit-text tiddler="$:/language/DefaultNewTiddlerTitle" default="" tag="input"/> | |<$link to="$:/config/NewJournal/Title"><> |<$edit-text tiddler="$:/config/NewJournal/Title" default="" tag="input"/> | -|<$link to="$:/config/NewJournal/Text"><> |<$edit tiddler="$:/config/NewJournal/Text" tag="textarea" class="tc-edit-texteditor" default=""/> | +|<$link to="$:/config/NewJournal/Text"><> |<$edit tiddler="$:/config/NewJournal/Text" class="tc-edit-texteditor" default="" autoHeight="yes"/> | |<$link to="$:/config/NewTiddler/Tags"><> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><><$action-listops $tiddler=<> $field="text" $subfilter={{{ [get[tags]] }}}/><$action-setfield $tiddler=<> tags=""/> | |<$link to="$:/config/NewJournal/Tags"><> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><><$action-listops $tiddler=<> $field="text" $subfilter={{{ [get[tags]] }}}/><$action-setfield $tiddler=<> tags=""/> | |<$link to="$:/config/AutoFocus"><> |{{$:/snippets/minifocusswitcher}} | diff --git a/core/ui/ControlPanel/Modals/AddPlugins.tid b/core/ui/ControlPanel/Modals/AddPlugins.tid index ce8612b72..56d3d5085 100644 --- a/core/ui/ControlPanel/Modals/AddPlugins.tid +++ b/core/ui/ControlPanel/Modals/AddPlugins.tid @@ -211,7 +211,7 @@ $:/state/add-plugin-info/$(connectionTiddler)$/$(assetInfo)$
\end -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] \whitespace trim
diff --git a/core/ui/ControlPanel/Parsing.tid b/core/ui/ControlPanel/Parsing.tid index 818d1f292..3a3173875 100644 --- a/core/ui/ControlPanel/Parsing.tid +++ b/core/ui/ControlPanel/Parsing.tid @@ -12,7 +12,7 @@ field="text" checked="enable" unchecked="disable" default="enable"> -<> +<> \end diff --git a/core/ui/ControlPanel/Settings.tid b/core/ui/ControlPanel/Settings.tid index f4a4b13c2..74004ffa0 100644 --- a/core/ui/ControlPanel/Settings.tid +++ b/core/ui/ControlPanel/Settings.tid @@ -2,18 +2,6 @@ title: $:/core/ui/ControlPanel/Settings tags: $:/tags/ControlPanel caption: {{$:/language/ControlPanel/Settings/Caption}} -\define lingo-base() $:/language/ControlPanel/Settings/ - -<> - -<$list filter="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/Settings]]"> - -
- -!! <$link><$transclude field="caption"/> - -<$transclude/> - -
- - +
+<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/ControlPanel/SettingsTab]!has[draft.of]]" default="$:/core/ui/ControlPanel/Settings/TiddlyWiki" explicitState="$:/state/tab--697582678"/> +
\ No newline at end of file diff --git a/plugins/tiddlywiki/codemirror/ui/controlpanel/tiddlywiki.tid b/core/ui/ControlPanel/TiddlyWiki.tid similarity index 96% rename from plugins/tiddlywiki/codemirror/ui/controlpanel/tiddlywiki.tid rename to core/ui/ControlPanel/TiddlyWiki.tid index f88865997..40be32139 100644 --- a/plugins/tiddlywiki/codemirror/ui/controlpanel/tiddlywiki.tid +++ b/core/ui/ControlPanel/TiddlyWiki.tid @@ -1,6 +1,7 @@ title: $:/core/ui/ControlPanel/Settings/TiddlyWiki tags: $:/tags/ControlPanel/SettingsTab caption: TiddlyWiki +list-before: \define lingo-base() $:/language/ControlPanel/Settings/ diff --git a/core/ui/DownloadFullWiki.tid b/core/ui/DownloadFullWiki.tid new file mode 100644 index 000000000..bfae2ceb6 --- /dev/null +++ b/core/ui/DownloadFullWiki.tid @@ -0,0 +1,18 @@ +title: $:/core/ui/DownloadFullWiki + +\whitespace trim +\rules except wikilink + +To download the standard single-file version of your wiki: + +<$wikify name="site-title" text={{$:/config/SaveWikiButton/Filename}}> +<$let publishFilter="""-[[$:/config/SaveWikiButton/Template]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]]"""> +<$button tooltip="Download fully standalone wiki" aria-label="download full wiki" class="tc-btn-big-green"> +<$action-sendmessage $message="tm-download-file" $param="$:/core/save/all" publishFilter=<> filename=<>/> +{{$:/core/images/download-button}} + +Download full wiki + + + + \ No newline at end of file diff --git a/core/ui/EditTemplate.tid b/core/ui/EditTemplate.tid index b63a02ee2..6ad84a139 100644 --- a/core/ui/EditTemplate.tid +++ b/core/ui/EditTemplate.tid @@ -1,7 +1,13 @@ +code-body: yes title: $:/core/ui/EditTemplate -\define delete-edittemplate-state-tiddlers() <$action-deletetiddler $filter="[] [prefix] [] [] [] [] [] [] []"/> +\define delete-edittemplate-state-tiddlers() +<$set name="safeNewFieldValueTiddlerPrefix" value=<> emptyValue=<> > + <$action-deletetiddler $filter="[] [prefix[$:/temp/NewFieldValue]prefix] [] [] [] [] [] [] []"/> + +\end + \define get-field-value-tiddler-filter() [subfiltersha256[16]addprefix[/]addprefix] \define get-field-editor-filter() [get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}] @@ -41,9 +47,7 @@ title: $:/core/ui/EditTemplate <$keyboard key="((cancel-edit-tiddler))" actions=<> tag="div"> <$keyboard key="((save-tiddler))" actions=<> tag="div"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/EditTemplate]!has[draft.of]]" variable="listItem"> -<$set name="tv-config-toolbar-class" filter="[] [encodeuricomponent[]addprefix[tc-btn-]]"> <$transclude tiddler=<>/> - diff --git a/core/ui/EditTemplate/Preview/output.tid b/core/ui/EditTemplate/Preview/output.tid index 4e5bf0e33..5c53d8c22 100644 --- a/core/ui/EditTemplate/Preview/output.tid +++ b/core/ui/EditTemplate/Preview/output.tid @@ -2,7 +2,7 @@ title: $:/core/ui/EditTemplate/body/preview/output tags: $:/tags/EditPreview caption: {{$:/language/EditTemplate/Body/Preview/Type/Output}} -\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!has[draft.of]] +\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Macro/View/Body]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View/Body]!is[draft]] <$set name="tv-tiddler-preview" value="yes"> <$transclude tiddler={{{ [] :cascade[all[shadows+tiddlers]tag[$:/tags/ViewTemplateBodyFilter]!is[draft]get[text]] :and[!is[blank]else[$:/core/ui/ViewTemplate/body/default]] }}} /> diff --git a/core/ui/EditTemplate/body/default.tid b/core/ui/EditTemplate/body/default.tid index a2128efb0..d004032f1 100644 --- a/core/ui/EditTemplate/body/default.tid +++ b/core/ui/EditTemplate/body/default.tid @@ -1,5 +1,9 @@ title: $:/core/ui/EditTemplate/body/default +\function edit-preview-state() +[{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[] +[get[text]] :else[[no]] +\end + \define config-visibility-title() $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$ \end @@ -10,15 +14,18 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$ \whitespace trim <$let - edit-preview-state={{{ [{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[] }}} + qualified-preview-state=<> + editPreviewStateTiddler={{{ [{$:/config/ShowEditPreview/PerTiddler}!match[yes]then[$:/state/showeditpreview]] :else[] }}} importTitle=<> importState=<> > <$dropzone importTitle=<> autoOpenOnImport="no" contentTypesFilter={{$:/config/Editor/ImportContentTypesFilter}} class="tc-dropzone-editor" enable={{{ [{$:/config/DragAndDrop/Enable}match[no]] :else[subfilter{$:/config/Editor/EnableImportFilter}then[yes]else[no]] }}} filesOnly="yes" actions=<> > -<$reveal stateTitle=<> type="match" text="yes" tag="div"> -
+
+
match[yes]then[tc-tiddler-preview]else[tc-tiddler-preview-hidden]] [[tc-tiddler-editor]] +[join[ ]] }}}> <$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/> +<$list filter="[get[text]match[yes]]" variable="ignore"> +
<$transclude tiddler={{$:/state/editpreviewtype}} mode="inline"> @@ -29,13 +36,12 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
+ +
- -<$reveal stateTitle=<> type="nomatch" text="yes" tag="div"> +
-<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/> - - + diff --git a/core/ui/EditTemplate/controls.tid b/core/ui/EditTemplate/controls.tid index 3e2f5e3f3..3e94d371d 100644 --- a/core/ui/EditTemplate/controls.tid +++ b/core/ui/EditTemplate/controls.tid @@ -7,6 +7,6 @@ $:/config/EditToolbarButtons/Visibility/$(listItem)$ \whitespace trim
<$view field="title"/> -<$list filter="[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$reveal type="nomatch" state=<> text="hide"><$transclude tiddler=<>/> +<$list filter="[all[shadows+tiddlers]tag[$:/tags/EditToolbar]!has[draft.of]]" variable="listItem"><$let tv-config-toolbar-class={{{ [enlist] [encodeuricomponent[]addprefix[tc-btn-]] +[join[ ]]}}}><$reveal type="nomatch" state=<> text="hide"><$transclude tiddler=<>/>
diff --git a/core/ui/EditTemplate/fields.tid b/core/ui/EditTemplate/fields.tid index 6173d9b76..0edc33505 100644 --- a/core/ui/EditTemplate/fields.tid +++ b/core/ui/EditTemplate/fields.tid @@ -10,6 +10,10 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$ [[hide]] -[title{$(config-title)$}] \end + +\define get-field-value-tiddler-filter() [subfiltersha256[16]addprefix[/]addprefix] +\define get-field-editor-filter() [get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}] + \define current-tiddler-new-field-selector() [data-tiddler-title="$(currentTiddlerCSSescaped)$"] .tc-edit-field-add-name-wrapper input \end @@ -17,7 +21,9 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$ \define new-field-actions() \whitespace trim <$action-sendmessage $message="tm-add-field" $name={{{ [get[text]] }}} $value={{{ [get[text]] :map[subfilterget[text]] }}}/> -<$action-deletetiddler $filter="[] [prefix] [] []"/> +<$set name="safeNewFieldValueTiddlerPrefix" value=<> emptyValue=<> > + <$action-deletetiddler $filter="[] [prefix[$:/temp/NewFieldValue]prefix] [] []"/> + <$action-sendmessage $message="tm-focus-selector" $param=<>/> \end @@ -48,11 +54,13 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$ \whitespace trim <$vars name={{{ [get[text]] }}}> <$reveal type="nomatch" text="" default=<>> -<$button tooltip=<>> +<$button tooltip={{$:/language/EditTemplate/Fields/Add/Button/Hint}}> <$action-sendmessage $message="tm-add-field" $name=<> $value={{{ [subfilterget[text]] }}}/> -<$action-deletetiddler $filter="[] [prefix] [] []"/> +<$set name="safeNewFieldValueTiddlerPrefix" value=<> emptyValue=<> > + <$action-deletetiddler $filter="[] [prefix[$:/temp/NewFieldValue]prefix] [] []"/> + <> @@ -65,6 +73,7 @@ $value={{{ [subfilterget[text]] }}}/> \end \whitespace trim +<$set name="newFieldValueTiddlerPrefix" value=<> emptyValue=<> >
@@ -80,7 +89,7 @@ $value={{{ [subfilterget[text]] }}}/> @@ -148,3 +157,4 @@ $value={{{ [subfilterget[text]] }}}/> + \ No newline at end of file diff --git a/core/ui/EditTemplate/tags.tid b/core/ui/EditTemplate/tags.tid index 8d829b30e..5084478b4 100644 --- a/core/ui/EditTemplate/tags.tid +++ b/core/ui/EditTemplate/tags.tid @@ -14,8 +14,8 @@ color:$(foregroundColor)$; \define tag-body-inner(colour,fallbackTarget,colourA,colourB,icon,tagField:"tags") \whitespace trim <$vars foregroundColor=<> backgroundColor="""$colour$"""> -> class="tc-tag-label tc-tag-list-item tc-small-gap-right"> -<$transclude tiddler="""$icon$"""/><$view field="title" format="text" /> +> class="tc-tag-label tc-tag-list-item tc-small-gap-right" data-tag-title=<>> +<$transclude tiddler="""$icon$"""/><$view field="title" format="text"/> <$button class="tc-btn-invisible tc-remove-tag-button" style=<>><$action-listops $tiddler=<> $field=<<__tagField__>> $subfilter="-[{!!title}]"/>{{$:/core/images/close-button}} diff --git a/core/ui/EditTemplate/type.tid b/core/ui/EditTemplate/type.tid index faa89639f..c1c38b72a 100644 --- a/core/ui/EditTemplate/type.tid +++ b/core/ui/EditTemplate/type.tid @@ -10,7 +10,7 @@ first-search-filter: [all[shadows+tiddlers]prefix[$:/language/Docs/Types/]sort[d <>
<$fieldmangler> -<$macrocall $name="keyboard-driven-input" tiddler=<> storeTitle=<> refreshTitle=<> selectionStateTitle=<> field="type" tag="input" default="" placeholder={{$:/language/EditTemplate/Type/Placeholder}} focusPopup=<> class="tc-edit-typeeditor tc-edit-texteditor tc-popup-handle" tabindex={{$:/config/EditTabIndex}} focus={{{ [{$:/config/AutoFocus}match[type]then[true]] ~[[false]] }}} cancelPopups="yes" configTiddlerFilter="[[$:/core/ui/EditTemplate/type]]" inputCancelActions=<>/><$button popup=<> class="tc-btn-invisible tc-btn-dropdown tc-small-gap" tooltip={{$:/language/EditTemplate/Type/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Type/Dropdown/Caption}}>{{$:/core/images/down-arrow}}<$button message="tm-remove-field" param="type" class="tc-btn-invisible tc-btn-icon" tooltip={{$:/language/EditTemplate/Type/Delete/Hint}} aria-label={{$:/language/EditTemplate/Type/Delete/Caption}}>{{$:/core/images/delete-button}}<$action-deletetiddler $filter="[] [] []"/> +<$macrocall $name="keyboard-driven-input" tiddler=<> storeTitle=<> refreshTitle=<> selectionStateTitle=<> field="type" tag="input" default="" placeholder={{$:/language/EditTemplate/Type/Placeholder}} focusPopup=<> class="tc-edit-typeeditor tc-edit-texteditor tc-popup-handle" tabindex={{$:/config/EditTabIndex}} focus={{{ [{$:/config/AutoFocus}match[type]then[true]] ~[[false]] }}} cancelPopups="yes" configTiddlerFilter="[[$:/core/ui/EditTemplate/type]]" inputCancelActions=<>/><$button popup=<> class="tc-btn-invisible tc-btn-dropdown tc-small-gap" tooltip={{$:/language/EditTemplate/Type/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Type/Dropdown/Caption}}>{{$:/core/images/down-arrow}}<$button message="tm-remove-field" param="type" class="tc-btn-invisible tc-btn-icon" tooltip={{$:/language/EditTemplate/Type/Delete/Hint}} aria-label={{$:/language/EditTemplate/Type/Delete/Caption}}>{{$:/core/images/delete-button}}<$action-deletetiddler $filter="[] [] [] []"/>
diff --git a/core/ui/EditToolbar/save.tid b/core/ui/EditToolbar/save.tid index c539009ee..3872e7674 100644 --- a/core/ui/EditToolbar/save.tid +++ b/core/ui/EditToolbar/save.tid @@ -3,16 +3,23 @@ tags: $:/tags/EditToolbar caption: {{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}} description: {{$:/language/Buttons/Save/Hint}} +\whitespace trim \define save-tiddler-button() \whitespace trim -<$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<>> -<> -<$list filter="[match[yes]]"> -{{$:/core/images/done-button}} - -<$list filter="[match[yes]]"> -<$text text={{$:/language/Buttons/Save/Caption}}/> - - +<$fieldmangler> + <$button + tooltip={{$:/language/Buttons/Save/Hint}} + aria-label={{$:/language/Buttons/Save/Caption}} + class=<> + > + <> + <$list filter="[match[yes]]"> + {{$:/core/images/done-button}} + + <$list filter="[match[yes]]"> + <$text text={{$:/language/Buttons/Save/Caption}}/> + + + \end <> diff --git a/core/ui/EditorToolbar/link-dropdown.tid b/core/ui/EditorToolbar/link-dropdown.tid index e2766935b..d2887a180 100644 --- a/core/ui/EditorToolbar/link-dropdown.tid +++ b/core/ui/EditorToolbar/link-dropdown.tid @@ -18,7 +18,7 @@ title: $:/core/ui/EditorToolbar/link-dropdown \define external-link() \whitespace trim -<$button class="tc-btn-invisible" style="width: auto; display: inline-block; background-colour: inherit;" actions=<>> +<$button class="tc-btn-invisible tc-btn-mini" style="width: auto; display: inline-block; background-colour: inherit;" actions=<>> {{$:/core/images/chevron-right}} \end @@ -45,7 +45,7 @@ title: $:/core/ui/EditorToolbar/link-dropdown <$reveal tag="span" state=<> type="nomatch" text=""> <> -<$button class="tc-btn-invisible" style="width: auto; display: inline-block; background-colour: inherit;"> +<$button class="tc-btn-invisible tc-btn-mini" style="width: auto; display: inline-block; background-colour: inherit;"> <><$set name="cssEscapedTitle" value={{{ [escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<>/> {{$:/core/images/close-button}} diff --git a/core/ui/EditorToolbar/preview.tid b/core/ui/EditorToolbar/preview.tid index 106b28d3c..d5c63eb5f 100644 --- a/core/ui/EditorToolbar/preview.tid +++ b/core/ui/EditorToolbar/preview.tid @@ -9,11 +9,8 @@ button-classes: tc-text-editor-toolbar-item-start-group shortcuts: ((preview)) \whitespace trim -<$reveal state=<> type="match" text="yes" tag="span"> -{{$:/core/images/preview-open}} -<$action-setfield $tiddler=<> $value="no"/> - -<$reveal state=<> type="nomatch" text="yes" tag="span"> -{{$:/core/images/preview-closed}} -<$action-setfield $tiddler=<> $value="yes"/> - + + <$transclude $tiddler={{{ [match[yes]then[$:/core/images/preview-open]else[$:/core/images/preview-closed]] }}} /> + +<$action-setfield $tiddler=<> $value={{{ [get[text]toggle[yes],[no]] }}} /> +<$action-sendmessage $message="tm-edit-text-operation" $param="focus-editor"/> diff --git a/core/ui/ExportTiddlyWikiCore.tid b/core/ui/ExportTiddlyWikiCore.tid index 8c85c87a4..4b913a020 100644 --- a/core/ui/ExportTiddlyWikiCore.tid +++ b/core/ui/ExportTiddlyWikiCore.tid @@ -1,11 +1,6 @@ title: $:/core/ui/ExportTiddlyWikiCore \define jsFileName() tiddlywikicore-$(version)$.js -\define noExportMsg() -It appears that you have a wiki with an external ~TiddlyWiki core. The export action cannot be performed. -

You will need to view the page source in your browser. Then go to the very bottom the the source, find the last ` \ No newline at end of file diff --git a/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid b/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid new file mode 100644 index 000000000..9a395abd6 --- /dev/null +++ b/editions/dev/tiddlers/system/configWikiParserRulesInlineWikilink.tid @@ -0,0 +1,3 @@ +title: $:/config/WikiParserRules/Inline/wikilink + +enable \ No newline at end of file diff --git a/editions/dev/tiddlers/system/doc-styles.tid b/editions/dev/tiddlers/system/doc-styles.tid new file mode 100644 index 000000000..24234d47a --- /dev/null +++ b/editions/dev/tiddlers/system/doc-styles.tid @@ -0,0 +1,40 @@ +created: 20150117152612000 +modified: 20230325101137075 +tags: $:/tags/Stylesheet +title: $:/editions/tw5.com/doc-styles +type: text/vnd.tiddlywiki + +a.doc-from-version.tc-tiddlylink { + display: inline-block; + border-radius: 1em; + background: <>; + color: <>; + fill: <>; + padding: 0 0.4em; + font-size: 0.7em; + text-transform: uppercase; + font-weight: bold; + line-height: 1.5; + vertical-align: text-bottom; +} + +a.doc-deprecated-version.tc-tiddlylink { + display: inline-block; + border-radius: 1em; + background: red; + color: <>; + fill: <>; + padding: 0 0.4em; + font-size: 0.7em; + text-transform: uppercase; + font-weight: bold; + line-height: 1.5; + vertical-align: text-bottom; +} + +.doc-deprecated-version svg, +.doc-from-version svg { + width: 1em; + height: 1em; + vertical-align: text-bottom; +} diff --git a/editions/dev/tiddlers/system/version-macros.tid b/editions/dev/tiddlers/system/version-macros.tid new file mode 100644 index 000000000..0fb7dcf12 --- /dev/null +++ b/editions/dev/tiddlers/system/version-macros.tid @@ -0,0 +1,14 @@ +code-body: yes +created: 20161008085627406 +modified: 20221007122259593 +tags: $:/tags/Macro +title: $:/editions/tw5.com/version-macros +type: text/vnd.tiddlywiki + +\define .from-version(version) +<$link to={{{ [<__version__>addprefix[Release ]] }}} class="doc-from-version">{{$:/core/images/warning}} New in: <$text text=<<__version__>>/> +\end + +\define .deprecated-since(version, superseded:"TODO-Link") +<$link to="Deprecated - What does it mean" class="doc-deprecated-version tc-btn-invisible">{{$:/core/images/warning}} Deprecated since: <$text text=<<__version__>>/> (see <$link to=<<__superseded__>>><$text text=<<__superseded__>>/>) +\end diff --git a/editions/dynaviewdemo/tiddlers/ViewTemplate.tid b/editions/dynaviewdemo/tiddlers/ViewTemplate.tid index cbf6eca2a..91bcfae86 100644 --- a/editions/dynaviewdemo/tiddlers/ViewTemplate.tid +++ b/editions/dynaviewdemo/tiddlers/ViewTemplate.tid @@ -5,7 +5,7 @@ title: $:/core/ui/ViewTemplate $:/state/folded/$(currentTiddler)$ \end \define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/> -\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] +\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!is[draft]] [all[shadows+tiddlers]tag[$:/tags/Global/View]!is[draft]] <$vars storyTiddler=<> tiddlerInfoState=<>>

> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [is[tiddler]then[tc-tiddler-exists]] [is[missing]!is[shadow]then[tc-tiddler-missing]] [is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [is[system]then[tc-tiddler-system]] [{!!class}] [tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}> <$set name="state" value={{{ [[$:/state/viewtemplate/visibility/]addsuffix] }}}> diff --git a/editions/empty/tiddlywiki.info b/editions/empty/tiddlywiki.info index 0eb8279d4..c754aad8a 100644 --- a/editions/empty/tiddlywiki.info +++ b/editions/empty/tiddlywiki.info @@ -8,19 +8,22 @@ ], "build": { "index": [ - "--rendertiddler","$:/core/save/all","index.html","text/plain"], + "--render","$:/core/save/all","index.html","text/plain"], "empty": [ - "--rendertiddler","$:/core/save/all","empty.html","text/plain", - "--rendertiddler","$:/core/save/all","empty.hta","text/plain"], + "--render","$:/core/save/all","empty.html","text/plain", + "--render","$:/core/save/all","empty.hta","text/plain"], + "emptyexternalcore": [ + "--render","$:/core/save/offline-external-js","empty-external-core.html","text/plain", + "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"], "externalimages": [ "--savetiddlers","[is[image]]","images", "--setfield","[is[image]]","_canonical_uri","$:/core/templates/canonical-uri-external-image","text/plain", "--setfield","[is[image]]","text","","text/plain", - "--rendertiddler","$:/core/save/all","externalimages.html","text/plain"], + "--render","$:/core/save/all","externalimages.html","text/plain"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"] } -} \ No newline at end of file +} diff --git a/editions/es-ES-server/tiddlers/system/favicon.ico b/editions/es-ES-server/tiddlers/system/favicon.ico deleted file mode 100644 index 3765a9a88..000000000 Binary files a/editions/es-ES-server/tiddlers/system/favicon.ico and /dev/null differ diff --git a/editions/es-ES-server/tiddlers/system/favicon.png b/editions/es-ES-server/tiddlers/system/favicon.png new file mode 100644 index 000000000..75be8e27d Binary files /dev/null and b/editions/es-ES-server/tiddlers/system/favicon.png differ diff --git a/editions/es-ES-server/tiddlers/system/favicon.ico.meta b/editions/es-ES-server/tiddlers/system/favicon.png.meta similarity index 53% rename from editions/es-ES-server/tiddlers/system/favicon.ico.meta rename to editions/es-ES-server/tiddlers/system/favicon.png.meta index 2f3e81713..76d0be1a8 100644 --- a/editions/es-ES-server/tiddlers/system/favicon.ico.meta +++ b/editions/es-ES-server/tiddlers/system/favicon.png.meta @@ -1,2 +1,2 @@ title: $:/favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/es-ES/tiddlers/$__Acknowledgements.tid b/editions/es-ES/tiddlers/$__Acknowledgements.tid index 48074d928..d907bc9e6 100644 --- a/editions/es-ES/tiddlers/$__Acknowledgements.tid +++ b/editions/es-ES/tiddlers/$__Acknowledgements.tid @@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki TiddlyWiki incorpora código de los siguientes proyectos OpenSource: * [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]] -* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]] +* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]] * [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]] ...y materiales de estos otros proyectos: diff --git a/editions/es-ES/tiddlers/Forums.tid b/editions/es-ES/tiddlers/Forums.tid index 63ecc4339..57af7d0f2 100644 --- a/editions/es-ES/tiddlers/Forums.tid +++ b/editions/es-ES/tiddlers/Forums.tid @@ -12,7 +12,9 @@ Son listas de correo en las que hablamos de ~TiddlyWiki: pedimos ayuda, anunciam Puedes participar a través de la página web asociada, o suscribirte via mail. -!!Usuarios +!! Usuarios + +[[Foro oficial de TiddlyWiki| https://talk.tiddlywiki.org/]] [[Grupo principal de TiddlyWiki| http://groups.google.com/group/TiddlyWiki]] @@ -25,10 +27,7 @@ o síguenos [[en Twitter|http://twitter.com/TiddlyWiki]] si quieres recibir las !! Desarrolladores -[[Grupo de desarrollo de TiddlyWiki|http://groups.google.com/group/TiddlyWikiDev]] - ->No necesitas tener cuenta en Google para acceder al grupo. Suscríbete igualmente enviando un mail a: -*mailto:tiddlywikidev+subscribe@googlegroups.com. +[[Foro de desarrollo de TiddlyWiki|https://talk.tiddlywiki.org/c/devs]] Accede a nuestra [[página de desarrollo|https://github.com/Jermolene/TiddlyWiki5]] en GitHub y haz tu contribución. diff --git a/editions/es-ES/tiddlers/GettingStarted_-_Chrome.tid b/editions/es-ES/tiddlers/GettingStarted_-_Chrome.tid index 7b7bef150..c23d2fbbc 100644 --- a/editions/es-ES/tiddlers/GettingStarted_-_Chrome.tid +++ b/editions/es-ES/tiddlers/GettingStarted_-_Chrome.tid @@ -7,4 +7,4 @@ type: text/vnd.tiddlywiki En Google Chrome, TiddlyWiki sólo puede guardar cambios usando el módulo alternativo de guardado compatible con HTML5 -{{Saving with the HTML5 fallback saver}} +{{Saving with the HTML5 saver}} diff --git a/editions/es-ES/tiddlers/HelloThere.tid b/editions/es-ES/tiddlers/HelloThere.tid index 0b1cea4bb..c08a27e7d 100644 --- a/editions/es-ES/tiddlers/HelloThere.tid +++ b/editions/es-ES/tiddlers/HelloThere.tid @@ -20,8 +20,8 @@ BIenvenido a TiddlyWiki, un bloc de notas [[no lineal|Philosophy of Tiddlers]] Al revés que los servicios online convencionales, TiddlyWiki te deja escoger dónde quieres guardar tus datos, garantizándote que, por más que pase el tiempo, podrás seguir usando en el futuro las notas que tomes hoy.
- -{{$:/core/images/mail}} ~TiddlyWiki en Google Groups + +{{$:/core/images/mail}} Foro oficial de ~TiddlyWiki {{$:/core/images/video}} ~TiddlyWiki en ~YouTube diff --git a/editions/es-ES/tiddlers/Saving_with_the_HTML5_fallback_saver.tid b/editions/es-ES/tiddlers/Saving_with_the_HTML5_fallback_saver.tid index ac599a14c..b1a703972 100644 --- a/editions/es-ES/tiddlers/Saving_with_the_HTML5_fallback_saver.tid +++ b/editions/es-ES/tiddlers/Saving_with_the_HTML5_fallback_saver.tid @@ -6,30 +6,4 @@ tags: Saving title: Saving with the HTML5 fallback saver type: text/vnd.tiddlywiki -Este método para guardar cambios es un poco rudimentario porque requiere intervención manual para cada acción de guardado. Tiene, sin embargo, la ventaja de que funciona en casi todos los navegadores de escritorio y en muchos navegadores móviles. - -# Descarga un TiddlyWiki en blanco pulsando este botón - -#> {{$:/editions/es-ES/snippets/download-empty-button}} - -#>Si el botón no funciona, guarda este enlace: https://tiddlywiki.com/languages/es-ES/empty.html - -#> Seguramente el navegador te pida que confirmes la descarga - -#Localiza el archivo que acabas de descargar - -#*Puedes cambiarle el nombre, siempre que mantengas la extensión `.html` o `.htm` - -#Abre el archivo en el navegador - -# Crea un nuevo tiddler usando el botón ''Nuevo tiddler'' {{$:/core/images/new-button}} de la barra lateral. Escribe algo en él y haz clic en el botón ''OK'' {{$:/core/images/done-button}} - -# Guarda los cambios con el botón ''Guardar cambios'' {{$:/core/images/save-button}} de la barra lateral - -# El navegador descargará una copia del wiki que incluye tus cambios. - -# Localiza el archivo nuevo y ábrelo en el navegador - -# Comprueba que los cambios se han guardado correctamente - -''Consejo'': la mayoría de navegadores permiten la opción de especificar la localización de cada descarga, en lugar de descargar a la carpeta por defecto. Esta opción te permite "planchar" tu archivo con la nueva versión. +[[Saving with the HTML5 saver]] \ No newline at end of file diff --git a/editions/es-ES/tiddlers/Saving_with_the_HTML5_saver.tid b/editions/es-ES/tiddlers/Saving_with_the_HTML5_saver.tid new file mode 100644 index 000000000..a68a50828 --- /dev/null +++ b/editions/es-ES/tiddlers/Saving_with_the_HTML5_saver.tid @@ -0,0 +1,35 @@ +caption: Guardar con módulo HTML5 +created: 20131129092604900 +es-title: Guardar con el módulo alternativo de guardado +modified: 20160603131518256 +tags: Saving +title: Saving with the HTML5 saver +type: text/vnd.tiddlywiki + +Este método para guardar cambios es un poco rudimentario porque requiere intervención manual para cada acción de guardado. Tiene, sin embargo, la ventaja de que funciona en casi todos los navegadores de escritorio y en muchos navegadores móviles. + +# Descarga un TiddlyWiki en blanco pulsando este botón + +#> {{$:/editions/es-ES/snippets/download-empty-button}} + +#>Si el botón no funciona, guarda este enlace: https://tiddlywiki.com/languages/es-ES/empty.html + +#> Seguramente el navegador te pida que confirmes la descarga + +#Localiza el archivo que acabas de descargar + +#*Puedes cambiarle el nombre, siempre que mantengas la extensión `.html` o `.htm` + +#Abre el archivo en el navegador + +# Crea un nuevo tiddler usando el botón ''Nuevo tiddler'' {{$:/core/images/new-button}} de la barra lateral. Escribe algo en él y haz clic en el botón ''OK'' {{$:/core/images/done-button}} + +# Guarda los cambios con el botón ''Guardar cambios'' {{$:/core/images/save-button}} de la barra lateral + +# El navegador descargará una copia del wiki que incluye tus cambios. + +# Localiza el archivo nuevo y ábrelo en el navegador + +# Comprueba que los cambios se han guardado correctamente + +''Consejo'': la mayoría de navegadores permiten la opción de especificar la localización de cada descarga, en lugar de descargar a la carpeta por defecto. Esta opción te permite "planchar" tu archivo con la nueva versión. diff --git a/editions/es-ES/tiddlers/Typography.tid b/editions/es-ES/tiddlers/Typography.tid index 58edf9220..47d3a05ce 100644 --- a/editions/es-ES/tiddlers/Typography.tid +++ b/editions/es-ES/tiddlers/Typography.tid @@ -8,7 +8,7 @@ type: text/vnd.tiddlywiki Se recomienda el uso de las [[macros de documentación|Documentation Macros]] para facilitar las futuras tareas de mantenimiento del texto frente a nuevos cambios y actualizaciones. -Se recomienda precaución en el uso arbitrario de estilos directos de formato (''negrita'', //cursiva// ...etc). Si se puede usar una macro, conviene usarla. Si no existe la macro adecuada, se puede crear o, si no se sabe cómo, pedir su creación en el [[Grupo de Google|http://groups.google.com/group/TiddlyWiki]]. +Se recomienda precaución en el uso arbitrario de estilos directos de formato (''negrita'', //cursiva// ...etc). Si se puede usar una macro, conviene usarla. Si no existe la macro adecuada, se puede crear o, si no se sabe cómo, pedir su creación en el [[Foro de TiddlyWiki|https://talk.tiddlywiki.org/]]. Por el mismo motivo, se aconseja el uso de acentos graves `...` para transcribir fragmentos de código y ~WikiText, pero no para nombres de cosas tales como campos, operadores, variables o widgets. Estas tienen su macro correspondiente. diff --git a/editions/es-ES/tiddlers/images/favicon.ico b/editions/es-ES/tiddlers/images/favicon.ico deleted file mode 100644 index d4fae0448..000000000 Binary files a/editions/es-ES/tiddlers/images/favicon.ico and /dev/null differ diff --git a/editions/es-ES/tiddlers/images/favicon.png b/editions/es-ES/tiddlers/images/favicon.png new file mode 100644 index 000000000..d797bbe8d Binary files /dev/null and b/editions/es-ES/tiddlers/images/favicon.png differ diff --git a/editions/es-ES/tiddlers/images/favicon.ico.meta b/editions/es-ES/tiddlers/images/favicon.png.meta similarity index 53% rename from editions/es-ES/tiddlers/images/favicon.ico.meta rename to editions/es-ES/tiddlers/images/favicon.png.meta index 2f3e81713..76d0be1a8 100644 --- a/editions/es-ES/tiddlers/images/favicon.ico.meta +++ b/editions/es-ES/tiddlers/images/favicon.png.meta @@ -1,2 +1,2 @@ title: $:/favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/es-ES/tiddlers/images/green_favicon.ico b/editions/es-ES/tiddlers/images/green_favicon.ico deleted file mode 100644 index 06e5f8e80..000000000 Binary files a/editions/es-ES/tiddlers/images/green_favicon.ico and /dev/null differ diff --git a/editions/es-ES/tiddlers/images/green_favicon.png b/editions/es-ES/tiddlers/images/green_favicon.png new file mode 100644 index 000000000..ac96b571f Binary files /dev/null and b/editions/es-ES/tiddlers/images/green_favicon.png differ diff --git a/editions/es-ES/tiddlers/images/green_favicon.ico.meta b/editions/es-ES/tiddlers/images/green_favicon.png.meta similarity index 59% rename from editions/es-ES/tiddlers/images/green_favicon.ico.meta rename to editions/es-ES/tiddlers/images/green_favicon.png.meta index f2e1cfa3c..1f2a3ecc0 100644 --- a/editions/es-ES/tiddlers/images/green_favicon.ico.meta +++ b/editions/es-ES/tiddlers/images/green_favicon.png.meta @@ -1,2 +1,2 @@ title: $:/green_favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/es-ES/tiddlywiki.info b/editions/es-ES/tiddlywiki.info index b72f0b5ee..466e87c01 100644 --- a/editions/es-ES/tiddlywiki.info +++ b/editions/es-ES/tiddlywiki.info @@ -1,6 +1,7 @@ { "description": "Spanish (Spain) edition", "plugins": [ + "tiddlywiki/internals" ], "themes": [ "tiddlywiki/vanilla", @@ -9,8 +10,7 @@ "tiddlywiki/seamless", "tiddlywiki/centralised", "tiddlywiki/tight", - "tiddlywiki/readonly", - "tiddlywiki/internals" + "tiddlywiki/readonly" ], "languages": [ "es-ES" diff --git a/editions/fr-FR-server/tiddlers/system/favicon.ico b/editions/fr-FR-server/tiddlers/system/favicon.ico deleted file mode 100644 index 3765a9a88..000000000 Binary files a/editions/fr-FR-server/tiddlers/system/favicon.ico and /dev/null differ diff --git a/editions/fr-FR-server/tiddlers/system/favicon.ico.meta b/editions/fr-FR-server/tiddlers/system/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/fr-FR-server/tiddlers/system/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/fr-FR-server/tiddlers/system/favicon.png b/editions/fr-FR-server/tiddlers/system/favicon.png new file mode 100644 index 000000000..75be8e27d Binary files /dev/null and b/editions/fr-FR-server/tiddlers/system/favicon.png differ diff --git a/editions/fr-FR-server/tiddlers/system/favicon.png.meta b/editions/fr-FR-server/tiddlers/system/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/fr-FR-server/tiddlers/system/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/fr-FR/tiddlers/$__Acknowledgements.tid b/editions/fr-FR/tiddlers/$__Acknowledgements.tid index 1adf217a0..6e9f6e0e5 100644 --- a/editions/fr-FR/tiddlers/$__Acknowledgements.tid +++ b/editions/fr-FR/tiddlers/$__Acknowledgements.tid @@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki TiddlyWiki intègre du code provenant de ces excellents projets OpenSource<> * [[The Stanford Javascript Crypto Library|http://bitwiseshiftleft.github.io/sjcl/]] -* [[The Jasmine JavaScript Test Framework|http://pivotal.github.io/jasmine/]] +* [[The Jasmine JavaScript Test Framework|https://jasmine.github.io/]] * [[Normalize.css by Nicolas Gallagher|http://necolas.github.io/normalize.css/]] Et des contenus provenenant de ces sources<> diff --git a/editions/fr-FR/tiddlers/GettingStarted - Chrome.tid b/editions/fr-FR/tiddlers/GettingStarted - Chrome.tid index aa7ae96a2..e8e752bf0 100644 --- a/editions/fr-FR/tiddlers/GettingStarted - Chrome.tid +++ b/editions/fr-FR/tiddlers/GettingStarted - Chrome.tid @@ -7,4 +7,4 @@ type: text/vnd.tiddlywiki Sous Google Chrome, <> ne parvient à sauvegarder les modifications qu'à l'aide de la solution de repli standard : le module de sauvegarde compatible HTML5. -{{Saving with the HTML5 fallback saver}} +{{Saving with the HTML5 saver}} diff --git a/editions/fr-FR/tiddlers/ReadMe.tid b/editions/fr-FR/tiddlers/ReadMe.tid index b02b564cb..aedcfd423 100644 --- a/editions/fr-FR/tiddlers/ReadMe.tid +++ b/editions/fr-FR/tiddlers/ReadMe.tid @@ -5,7 +5,7 @@ type: text/vnd.tiddlywiki \define tv-wikilink-template() https://tiddlywiki.com/static/$uri_doubleencoded$.html -<$importvariables filter="[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]"> +<$importvariables filter={{$:/core/config/GlobalImportFilter}}> Bienvenue sur <>, un carnet de notes personnel web et non-linéaire que tout le monde peut utiliser et conserver, sans dépendre d'une quelconque entreprise. diff --git a/editions/fr-FR/tiddlers/Saving with the HTML5 saver.tid b/editions/fr-FR/tiddlers/Saving with the HTML5 saver.tid new file mode 100644 index 000000000..34fe138ff --- /dev/null +++ b/editions/fr-FR/tiddlers/Saving with the HTML5 saver.tid @@ -0,0 +1,23 @@ +created: 20131129092604900 +fr-title: Sauvegarder avec l'enregistreur HTML 5 par défaut +modified: 20160526130128327 +tags: Saving +title: Saving with the HTML5 saver +type: text/vnd.tiddlywiki + +Cette manière d'enregistrer les modifications est assez pénible, car elle requiert une intervention manuelle à chaque enregistrement. Elle a l'avantage de fonctionner avec pratiquement tous les navigateurs tournant sur les ordinateurs de bureaux, et de nombreux navigateurs tournant sur appareils mobiles. + +# [[Téléchargez|Download]] un TiddlyWiki en cliquant sur ce bouton<> +#> {{$:/editions/fr-FR/snippets/download-empty-button}} +#> Si le bouton ne fonctionne pas, enregistrez ce lien<> https://tiddlywiki.com/languages/fr-FR/empty.html +#> Votre navigateur vous demandera peut-être d'accepter explicitement l'enregistrement avant qu'il démarre +# Localisez le fichier que vous venez de télécharger +#* Vous pouvez le renommer, mais assurez-vous de conserver l'extension `.html` ou `.htm` +# Ouvrez le fichier dans votre navigateur +# Essayez de créer un nouveau tiddler à l'aide du bouton ''nouveau tiddler'' {{$:/core/images/new-button}} de la barre latérale. Ajouter du contenu dans le tiddler, et cliquez sur le bouton ''terminé'' {{$:/core/images/done-button}} +# Enregistrez vos modifications en cliquant sur le bouton ''enregistrer les modifications'' {{$:/core/images/save-button}} de la barre latérale +# Votre navigateur téléchargera alors un nouvel exemplaire du wiki, avec vos modifications à l'intérieur +# Localisez ce nouveau fichier et ouvrez-le dans votre navigateur +# Vérifiez que vos modifications ont correctement été enregistrées + +''Truc'': la plupart des navigateurs peuvent être configurés pour proposer un chemin d'enregistrement à chaque téléchargement. Cela vous permet de sélectionner la version précédente du fichier et ainsi de la remplacer. diff --git a/editions/fr-FR/tiddlers/images/favicon.ico b/editions/fr-FR/tiddlers/images/favicon.ico deleted file mode 100644 index d4fae0448..000000000 Binary files a/editions/fr-FR/tiddlers/images/favicon.ico and /dev/null differ diff --git a/editions/fr-FR/tiddlers/images/favicon.ico.meta b/editions/fr-FR/tiddlers/images/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/fr-FR/tiddlers/images/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/fr-FR/tiddlers/images/favicon.png b/editions/fr-FR/tiddlers/images/favicon.png new file mode 100644 index 000000000..d797bbe8d Binary files /dev/null and b/editions/fr-FR/tiddlers/images/favicon.png differ diff --git a/editions/fr-FR/tiddlers/images/favicon.png.meta b/editions/fr-FR/tiddlers/images/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/fr-FR/tiddlers/images/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/fr-FR/tiddlers/images/green_favicon.ico b/editions/fr-FR/tiddlers/images/green_favicon.ico deleted file mode 100644 index 06e5f8e80..000000000 Binary files a/editions/fr-FR/tiddlers/images/green_favicon.ico and /dev/null differ diff --git a/editions/fr-FR/tiddlers/images/green_favicon.png b/editions/fr-FR/tiddlers/images/green_favicon.png new file mode 100644 index 000000000..ac96b571f Binary files /dev/null and b/editions/fr-FR/tiddlers/images/green_favicon.png differ diff --git a/editions/fr-FR/tiddlers/images/green_favicon.ico.meta b/editions/fr-FR/tiddlers/images/green_favicon.png.meta similarity index 59% rename from editions/fr-FR/tiddlers/images/green_favicon.ico.meta rename to editions/fr-FR/tiddlers/images/green_favicon.png.meta index f2e1cfa3c..1f2a3ecc0 100644 --- a/editions/fr-FR/tiddlers/images/green_favicon.ico.meta +++ b/editions/fr-FR/tiddlers/images/green_favicon.png.meta @@ -1,2 +1,2 @@ title: $:/green_favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/fr-FR/tiddlers/saving/Saving on Beaker Browser.tid b/editions/fr-FR/tiddlers/saving/Saving on Beaker Browser.tid deleted file mode 100644 index a1541c9bf..000000000 --- a/editions/fr-FR/tiddlers/saving/Saving on Beaker Browser.tid +++ /dev/null @@ -1,35 +0,0 @@ -caption: Beaker Browser -color: #FF8A65 -created: 20161229121316912 -delivery: App -description: Nouveau navigateur puissant pour Mac, Windows et Linux -fr-title: Enregistrer avec Beaker Browser -method: save -modified: 20220402105820520 -tags: Saving Windows Linux Mac -title: Saving on Beaker Browser -type: text/vnd.tiddlywiki - -<<.from-version "5.1.14">> <> intègre un module qui lui permet d'enregistrer les modifications directement avec [[Beaker Browser]], un navigateur internet en peer-to-peer expérimental. - -! Instructions - -# Téléchargez et installez Beaker Browser depuis https://beakerbrowser.com/ -# Lancez Beaker et si nécessaire ouvrez un onglet vers l'adresse `beaker:start` -# Cliquez sur le bouton <> en haut à gauche de la page -# Saisissez les détails sur votre site -# Cliquez sur le lien <> et sélectionnez le fichier `index.html` de votre <> -# Naviguez sur votre site en cliquant sur le lien vers `index.html`<<;>> il devrait s'ouvrir dans un nouvel onglet -# Essayez de créer des tiddlers et d'enregistrer les modifications - -Jusque là, le wiki est entièrement privé et les autres utilisateurs ne peuvent pas en voir le contenu, même en connaissant l'URL. Pour le partager avec d'autres utilisateurs<<:>> - -# Publiez vos modifications -## Visitez la page <> à l'aide du menu <> de Beaker Browser -## Sélectionnez votre site dans la liste -## Recherchez un encart <>. S'il n'est pas présent, passez au point suivant -## Cliquez sur le bouton <> -## Cliquez sur le bouton <> -# Partagez l'URL `dat:` -## Copiez l'URL de votre site à partir de la barre d'adresse et partagez-la avec d'autres utilisateurs -## Les autres utilisateurs devraient pouvoir accéder à votre site mais ils ne pourront pas le modifier avant d'en avoir fait leur propre clone diff --git a/editions/fr-FR/tiddlers/saving/Saving with the HTML5 fallback saver.tid b/editions/fr-FR/tiddlers/saving/Saving with the HTML5 fallback saver.tid index 24c9c7f4c..0e01be1f9 100644 --- a/editions/fr-FR/tiddlers/saving/Saving with the HTML5 fallback saver.tid +++ b/editions/fr-FR/tiddlers/saving/Saving with the HTML5 fallback saver.tid @@ -1,28 +1,7 @@ -caption: Enregistreur HTML5 -color: #7986cb created: 20131129092604900 -delivery: Saver -description: Technique un peu gênante mais universelle qui marche sur tous les navigateurs ou presque fr-title: Enregistreur HTML5 par défaut -method: save modified: 20220402105820520 -tags: Saving Chrome Firefox [[Internet Explorer]] Opera Safari Edge title: Saving with the HTML5 fallback saver type: text/vnd.tiddlywiki -Cette manière d'enregistrer les modifications est assez pénible, car elle requiert une intervention manuelle à chaque enregistrement. Elle a l'avantage de fonctionner avec pratiquement tous les navigateurs tournant sur les ordinateurs de bureaux, et de nombreux navigateurs tournant sur appareils mobiles. - -# [[Téléchargez|Download]] un TiddlyWiki en cliquant sur ce bouton<> -#> {{$:/editions/fr-FR/snippets/download-empty-button}} -#> Si le bouton ne fonctionne pas, enregistrez ce lien<> https://tiddlywiki.com/languages/fr-FR/empty.html -#> Votre navigateur vous demandera peut-être d'accepter explicitement l'enregistrement avant qu'il démarre -# Localisez le fichier que vous venez de télécharger -#* Vous pouvez le renommer, mais assurez-vous de conserver l'extension `.html` ou `.htm` -# Ouvrez le fichier dans votre navigateur -# Essayez de créer un nouveau tiddler à l'aide du bouton <<.icon $:/core/images/new-button>> ''nouveau tiddler'' de la barre latérale. Ajouter du contenu dans le tiddler, et cliquez sur le bouton <<.icon $:/core/images/done-button>> ''terminé'' -# Enregistrez vos modifications en cliquant sur le bouton <<.icon $:/core/images/save-button>> ''enregistrer les modifications'' de la barre latérale -# Votre navigateur téléchargera alors un nouvel exemplaire du wiki, avec vos modifications à l'intérieur -# Localisez ce nouveau fichier et ouvrez-le dans votre navigateur -# Vérifiez que vos modifications ont correctement été enregistrées - -''Astuce''<<:>> la plupart des navigateurs peuvent être configurés pour proposer un chemin d'enregistrement à chaque téléchargement. Cela vous permet de sélectionner la version précédente du fichier et ainsi de la remplacer. +[[Saving with the HTML5 saver]] \ No newline at end of file diff --git a/editions/fr-FR/tiddlywiki.info b/editions/fr-FR/tiddlywiki.info index a710d5775..186c610e6 100644 --- a/editions/fr-FR/tiddlywiki.info +++ b/editions/fr-FR/tiddlywiki.info @@ -1,6 +1,7 @@ { "description": "French (France) edition", "plugins": [ + "tiddlywiki/internals" ], "themes": [ "tiddlywiki/vanilla", @@ -9,8 +10,7 @@ "tiddlywiki/seamless", "tiddlywiki/centralised", "tiddlywiki/tight", - "tiddlywiki/readonly", - "tiddlywiki/internals" + "tiddlywiki/readonly" ], "languages": [ "fr-FR" diff --git a/editions/full/tiddlywiki.info b/editions/full/tiddlywiki.info index 0a716f60e..e5dc0b0f9 100644 --- a/editions/full/tiddlywiki.info +++ b/editions/full/tiddlywiki.info @@ -37,7 +37,6 @@ "de-AT", "de-DE", "el-GR", - "en-GB", "en-US", "es-ES", "fa-IR", diff --git a/editions/highlightdemo/tiddlywiki.info b/editions/highlightdemo/tiddlywiki.info index 3e824764b..075859c8c 100644 --- a/editions/highlightdemo/tiddlywiki.info +++ b/editions/highlightdemo/tiddlywiki.info @@ -11,11 +11,11 @@ ], "build": { "index": [ - "--rendertiddler","$:/core/save/all","highlightdemo.html","text/plain"], + "--render","$:/core/save/all","highlightdemo.html","text/plain"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"] } } diff --git a/editions/introduction/tiddlers/slides/CecilyMap.tid b/editions/introduction/tiddlers/slides/CecilyMap.tid index 01e969cad..3318198f0 100644 --- a/editions/introduction/tiddlers/slides/CecilyMap.tid +++ b/editions/introduction/tiddlers/slides/CecilyMap.tid @@ -4,17 +4,17 @@ type: application/json { "newTiddlerPosition": {"x": 360,"y": 100}, "positions": { - " ": {"x": 30,"y": 17,"w": 140,"h": 140, "r": -2}, - "Tiddlers": {"x": 60,"y": 15,"w": 140,"h": 140, "r": 10}, - "Links": {"x": 90,"y": 13,"w": 140,"h": 140, "r": -7}, - "Formatting": {"x": 120,"y": 18,"w": 140,"h": 140, "r": 5}, - "Images": {"x": 150,"y": 12,"w": 140,"h": 140, "r": -11}, - "Audio": {"x": 180,"y": 14,"w": 140,"h": 140, "r": 16}, - "Tags": {"x": 210,"y": 15,"w": 140,"h": 140, "r": 20}, - "Transclusion": {"x": 240,"y": 16,"w": 140,"h": 140, "r": -4}, - "Lists": {"x": 275,"y": 13,"w": 140,"h": 140, "r": 6}, - "Customisation": {"x": 310,"y": 19,"w": 140,"h": 140, "r": -5}, - "Plugins": {"x": 350,"y": 12,"w": 140,"h": 140, "r": 10}, - "Translations": {"x": 390,"y": 15,"w": 140,"h": 140, "r": 8} + " ": {"x": 30,"y": 17,"w": 120,"h": 120, "r": -2}, + "Tiddlers": {"x": 60,"y": 15,"w": 120,"h": 120, "r": 10}, + "Links": {"x": 90,"y": 13,"w": 120,"h": 120, "r": -7}, + "Formatting": {"x": 120,"y": 18,"w": 120,"h": 120, "r": 5}, + "Images": {"x": 150,"y": 12,"w": 120,"h": 120, "r": -11}, + "Audio": {"x": 180,"y": 14,"w": 120,"h": 120, "r": 16}, + "Tags": {"x": 210,"y": 15,"w": 120,"h": 120, "r": 20}, + "Transclusion": {"x": 240,"y": 16,"w": 120,"h": 120, "r": -4}, + "Lists": {"x": 275,"y": 13,"w": 120,"h": 120, "r": 6}, + "Customisation": {"x": 310,"y": 19,"w": 120,"h": 120, "r": -5}, + "Plugins": {"x": 350,"y": 12,"w": 120,"h": 120, "r": 10}, + "Translations": {"x": 390,"y": 15,"w": 120,"h": 120, "r": 8} } } \ No newline at end of file diff --git a/editions/introduction/tiddlers/slides/Formatting.tid b/editions/introduction/tiddlers/slides/Formatting.tid index d3a074967..7cce34a4a 100644 --- a/editions/introduction/tiddlers/slides/Formatting.tid +++ b/editions/introduction/tiddlers/slides/Formatting.tid @@ -8,6 +8,6 @@ Tiddlers can contain formatted text: Formatting is typed with special codes: -<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="10px"/> +<$edit-text tiddler="FormattingDemoText" class="tc-edit-texteditor" minHeight="100px"/> TiddlyWiki is not just for text. [[Images]] are first class citizens, too. diff --git a/editions/introduction/tiddlers/slides/blank.json b/editions/introduction/tiddlers/slides/blank.json index 6d507401f..e523d48d4 100644 --- a/editions/introduction/tiddlers/slides/blank.json +++ b/editions/introduction/tiddlers/slides/blank.json @@ -1,3 +1,3 @@ [ -{"title": " ", "text": "TiddlyWiki"} +{"title": " ", "text": "[[TiddlyWiki]]"} ] diff --git a/editions/introduction/tiddlywiki.info b/editions/introduction/tiddlywiki.info index a638ec142..680730452 100644 --- a/editions/introduction/tiddlywiki.info +++ b/editions/introduction/tiddlywiki.info @@ -24,7 +24,6 @@ "de-CH", "de-DE", "el-GR", - "en-GB", "en-US", "es-ES", "fa-IR", @@ -50,17 +49,6 @@ ], "build": { "index": [ - "--savetiddlers","[tag[external-image]]","images", - "--setfield","[tag[external-image]]","_canonical_uri","$:/core/templates/canonical-uri-external-image","text/plain", - "--setfield","[tag[external-image]]","text","","text/plain", - "--rendertiddler","$:/core/save/all","index.html","text/plain"], - "favicon": [ - "--savetiddler","$:/favicon.ico","favicon.ico", - "--savetiddler","$:/green_favicon.ico","static/favicon.ico"], - "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--rendertiddler","$:/core/save/all","index.html","text/plain"] } } diff --git a/editions/ja-JP/tiddlers/images/favicon.ico b/editions/ja-JP/tiddlers/images/favicon.ico deleted file mode 100644 index d4fae0448..000000000 Binary files a/editions/ja-JP/tiddlers/images/favicon.ico and /dev/null differ diff --git a/editions/ja-JP/tiddlers/images/favicon.ico.meta b/editions/ja-JP/tiddlers/images/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/ja-JP/tiddlers/images/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/ja-JP/tiddlers/images/favicon.png b/editions/ja-JP/tiddlers/images/favicon.png new file mode 100644 index 000000000..d797bbe8d Binary files /dev/null and b/editions/ja-JP/tiddlers/images/favicon.png differ diff --git a/editions/ja-JP/tiddlers/images/favicon.png.meta b/editions/ja-JP/tiddlers/images/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/ja-JP/tiddlers/images/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/ja-JP/tiddlers/images/green_favicon.ico b/editions/ja-JP/tiddlers/images/green_favicon.ico deleted file mode 100644 index 06e5f8e80..000000000 Binary files a/editions/ja-JP/tiddlers/images/green_favicon.ico and /dev/null differ diff --git a/editions/ja-JP/tiddlers/images/green_favicon.png b/editions/ja-JP/tiddlers/images/green_favicon.png new file mode 100644 index 000000000..ac96b571f Binary files /dev/null and b/editions/ja-JP/tiddlers/images/green_favicon.png differ diff --git a/editions/ja-JP/tiddlers/images/green_favicon.ico.meta b/editions/ja-JP/tiddlers/images/green_favicon.png.meta similarity index 59% rename from editions/ja-JP/tiddlers/images/green_favicon.ico.meta rename to editions/ja-JP/tiddlers/images/green_favicon.png.meta index f2e1cfa3c..1f2a3ecc0 100644 --- a/editions/ja-JP/tiddlers/images/green_favicon.ico.meta +++ b/editions/ja-JP/tiddlers/images/green_favicon.png.meta @@ -1,2 +1,2 @@ title: $:/green_favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/ja-JP/tiddlywiki.info b/editions/ja-JP/tiddlywiki.info index b6732ac05..3b4187547 100644 --- a/editions/ja-JP/tiddlywiki.info +++ b/editions/ja-JP/tiddlywiki.info @@ -1,6 +1,7 @@ { "description": "Japanese (Japan) edition", "plugins": [ + "tiddlywiki/internals" ], "themes": [ "tiddlywiki/vanilla", @@ -9,8 +10,7 @@ "tiddlywiki/seamless", "tiddlywiki/centralised", "tiddlywiki/tight", - "tiddlywiki/readonly", - "tiddlywiki/internals" + "tiddlywiki/readonly" ], "languages": [ "ja-JP" diff --git a/editions/katexdemo/tiddlywiki.info b/editions/katexdemo/tiddlywiki.info index 17233e8d0..bd07b3e28 100644 --- a/editions/katexdemo/tiddlywiki.info +++ b/editions/katexdemo/tiddlywiki.info @@ -11,11 +11,11 @@ ], "build": { "index": [ - "--rendertiddler","$:/core/save/all","katexdemo.html","text/plain"], + "--render","$:/core/save/all","katexdemo.html","text/plain"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"] } } diff --git a/editions/ko-KR-server/tiddlers/system/favicon.ico b/editions/ko-KR-server/tiddlers/system/favicon.ico deleted file mode 100644 index 3765a9a88..000000000 Binary files a/editions/ko-KR-server/tiddlers/system/favicon.ico and /dev/null differ diff --git a/editions/ko-KR-server/tiddlers/system/favicon.ico.meta b/editions/ko-KR-server/tiddlers/system/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/ko-KR-server/tiddlers/system/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/ko-KR-server/tiddlers/system/favicon.png b/editions/ko-KR-server/tiddlers/system/favicon.png new file mode 100644 index 000000000..75be8e27d Binary files /dev/null and b/editions/ko-KR-server/tiddlers/system/favicon.png differ diff --git a/editions/ko-KR-server/tiddlers/system/favicon.png.meta b/editions/ko-KR-server/tiddlers/system/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/ko-KR-server/tiddlers/system/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/ko-KR/tiddlers/images/favicon.ico b/editions/ko-KR/tiddlers/images/favicon.ico deleted file mode 100644 index d4fae0448..000000000 Binary files a/editions/ko-KR/tiddlers/images/favicon.ico and /dev/null differ diff --git a/editions/ko-KR/tiddlers/images/favicon.ico.meta b/editions/ko-KR/tiddlers/images/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/ko-KR/tiddlers/images/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/ko-KR/tiddlers/images/favicon.png b/editions/ko-KR/tiddlers/images/favicon.png new file mode 100644 index 000000000..d797bbe8d Binary files /dev/null and b/editions/ko-KR/tiddlers/images/favicon.png differ diff --git a/editions/ko-KR/tiddlers/images/favicon.png.meta b/editions/ko-KR/tiddlers/images/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/ko-KR/tiddlers/images/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/ko-KR/tiddlers/images/green_favicon.ico b/editions/ko-KR/tiddlers/images/green_favicon.ico deleted file mode 100644 index 06e5f8e80..000000000 Binary files a/editions/ko-KR/tiddlers/images/green_favicon.ico and /dev/null differ diff --git a/editions/ko-KR/tiddlers/images/green_favicon.png b/editions/ko-KR/tiddlers/images/green_favicon.png new file mode 100644 index 000000000..ac96b571f Binary files /dev/null and b/editions/ko-KR/tiddlers/images/green_favicon.png differ diff --git a/editions/ko-KR/tiddlers/images/green_favicon.ico.meta b/editions/ko-KR/tiddlers/images/green_favicon.png.meta similarity index 59% rename from editions/ko-KR/tiddlers/images/green_favicon.ico.meta rename to editions/ko-KR/tiddlers/images/green_favicon.png.meta index f2e1cfa3c..1f2a3ecc0 100644 --- a/editions/ko-KR/tiddlers/images/green_favicon.ico.meta +++ b/editions/ko-KR/tiddlers/images/green_favicon.png.meta @@ -1,2 +1,2 @@ title: $:/green_favicon.ico -type: image/x-icon +type: image/png diff --git a/editions/markdowndemo/tiddlers/DefaultTiddlers.tid b/editions/markdowndemo/tiddlers/DefaultTiddlers.tid index 0f4e00095..bd7c63120 100644 --- a/editions/markdowndemo/tiddlers/DefaultTiddlers.tid +++ b/editions/markdowndemo/tiddlers/DefaultTiddlers.tid @@ -1,4 +1,7 @@ title: $:/DefaultTiddlers [[HelloThere]] -[[MarkdownExample]] +$:/plugins/tiddlywiki/markdown +[[MarkdownTutorial]] +[[QuickDemo]] +[[QuickDemo Source]] diff --git a/editions/markdowndemo/tiddlers/HelloThere.tid b/editions/markdowndemo/tiddlers/HelloThere.tid index e818ddb59..c536d83ee 100644 --- a/editions/markdowndemo/tiddlers/HelloThere.tid +++ b/editions/markdowndemo/tiddlers/HelloThere.tid @@ -1,11 +1,9 @@ title: HelloThere -This is a demo of TiddlyWiki5 incorporating a plugin for parsing tiddlers written in the Markdown language. The plugin uses the [[Remarkable|https://github.com/jonschlinkert/remarkable]] Markdown parser internally. The MarkdownExample tiddler below is written in Markdown. +This is a demo of TiddlyWiki5 incorporating a plugin for parsing tiddlers written in the Markdown language. The plugin uses the [[markdown-it|https://github.com/markdown-it/markdown-it]] Markdown parser internally. The MarkdownTutorial tiddler below is written in Markdown. ! Installation To add the plugin to your own TiddlyWiki5, just drag this link to the browser window: -[[$:/plugins/tiddlywiki/markdown]] - -{{$:/plugins/tiddlywiki/markdown/usage}} \ No newline at end of file +[[$:/plugins/tiddlywiki/markdown]] \ No newline at end of file diff --git a/editions/markdowndemo/tiddlers/MarkdownExample.tid b/editions/markdowndemo/tiddlers/MarkdownTutorial.tid similarity index 96% rename from editions/markdowndemo/tiddlers/MarkdownExample.tid rename to editions/markdowndemo/tiddlers/MarkdownTutorial.tid index 9d8144c5f..c6b89eaed 100644 --- a/editions/markdowndemo/tiddlers/MarkdownExample.tid +++ b/editions/markdowndemo/tiddlers/MarkdownTutorial.tid @@ -1,4 +1,4 @@ -title: MarkdownExample +title: MarkdownTutorial type: text/x-markdown Markdown: Basics @@ -8,13 +8,13 @@ Getting the Gist of Markdown's Formatting Syntax ------------------------------------------------ This page offers a brief overview of what it's like to use Markdown. -The [syntax page] [s] provides complete, detailed documentation for +The [syntax page][s] provides complete, detailed documentation for every feature, but Markdown should be very easy to pick up simply by looking at a few examples of it in action. The examples on this page are written in a before/after style, showing example syntax and the HTML output produced by Markdown. -It's also helpful to simply try Markdown out; the [Dingus] [d] is a +It's also helpful to simply try Markdown out; the [Dingus][d] is a web application that allows you type your own Markdown-formatted text and translate it to XHTML. @@ -117,7 +117,7 @@ Output: Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, `+`, and `-`) as list markers. These three markers are -interchangable; this: +interchangeable; this: * Candy. * Gum. @@ -264,7 +264,7 @@ it easy to use Markdown to write about HTML example code: I strongly recommend against using any `` tags. I wish SmartyPants used named entities like `—` - instead of decimal-encoded entites like `—`. + instead of decimal-encoded entities like `—`. Output: @@ -273,7 +273,7 @@ Output:

I wish SmartyPants used named entities like &mdash; instead of decimal-encoded - entites like &#8212;.

+ entities like &#8212;.

To specify an entire block of pre-formatted code, indent every line of diff --git a/editions/markdowndemo/tiddlers/QuickDemo.tid b/editions/markdowndemo/tiddlers/QuickDemo.tid new file mode 100644 index 000000000..0bd83f5ed --- /dev/null +++ b/editions/markdowndemo/tiddlers/QuickDemo.tid @@ -0,0 +1,220 @@ +title: QuickDemo +type: text/markdown + + +# h1 Heading +## h2 Heading +### h3 Heading +#### h4 Heading +##### h5 Heading +###### h6 Heading + + +## Horizontal Rules + +____ + +--- + +**** + + +## Emphasis + + +**This is bold text** + +__This is bold text__ + +*This is italic text* + +_This is italic text_ + +~~Strikethrough~~ + + +## Blockquotes + + +> Blockquotes can also be nested... +>> ...by using additional greater-than signs right next to each other... +> > > ...or with spaces between arrows. + + +## Unordered List + + ++ Create a list by starting a line with `+`, `-`, or `*` ++ Sub-lists are made by indenting 2 spaces: + - Marker character change forces new list start: + * Ac tristique libero volutpat at + + Facilisis in pretium nisl aliquet + - Nulla volutpat aliquam velit ++ Very easy! + + +## Ordered List + + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + + +1. You can use sequential numbers... +1. ...or keep all the numbers as `1.` + +Start numbering with offset: + +57. foo +1. bar + + +## Code + + +Inline `code` + +Indented code + + // Some comments + line 1 of code + line 2 of code + line 3 of code + +Block code "fences" + +``` +Sample text here... +``` + + +## Syntax highlighting + +``` js +var foo = function (bar) { + return bar++; +}; + +console.log(foo(5)); +``` + + +## ~KaTeX + + +Equation $c = \pm\sqrt{a^2 + b^2}$ is typeset in inline mode. + +Display style: $$c = \pm\sqrt{a^2 + b^2}$$ + + +## Tables + + +| Attribute | Description | +| --------- | ----------- | +| multiple | select multiple files to download | +| param | parameter to be passed with the message | +| tooltip | optional tooltip text | + +Aligning columns: + +| Column A | Column B | Column C | +| :---- | :----: | ----: | +| is | is | is | +| left | nicely | right | +| aligned | centered | aligned | + + +## Links + + +[link text](http://google.com) + +[link with title](http://nodeca.github.io/pica/demo/ "title text!") + +link to tiddler [QuickDemo Source](#QuickDemo%20Source) + +URL can contain spaces if enclosed in brackets `<>`: [QuickDemo Source](<#QuickDemo Source>) + + +## Images + + +![Minion](https://octodex.github.com/images/minion.png) +![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") + +Like links, images also have a reference style syntax + +![Alt text][id] + +with a link reference defined later in the document. + +[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" + + +## Subscript & Superscript + + +- 19^th^ +- H~2~O + + +## \ + + +++Inserted text++ + + +## \ + + +==Marked text== + + +## Footnotes + + +Footnote 1 link[^first]. + +Footnote 2 link[^second]. + +Inline footnote^[Text of inline footnote] definition. + +Duplicated footnote reference[^second]. + +[^first]: Footnote **can have markup** + + and multiple paragraphs. + +[^second]: Footnote text. + + +## Definition Lists + + +Term 1 + +: Definition 1 +with lazy continuation. + +Term 2 with *inline markup* + +: Definition 2 + + { some code, part of Definition 2 } + + Third paragraph of definition 2. + +_Compact style:_ + +Term 1 + ~ Definition 1 + +Term 2 + ~ Definition 2a + ~ Definition 2b diff --git a/editions/markdowndemo/tiddlers/QuickDemoSource.tid b/editions/markdowndemo/tiddlers/QuickDemoSource.tid new file mode 100644 index 000000000..c0d9167f8 --- /dev/null +++ b/editions/markdowndemo/tiddlers/QuickDemoSource.tid @@ -0,0 +1,5 @@ +title: QuickDemo Source + +<$let tiddler="QuickDemo"> +<$codeblock code={{{ [get[text]] }}} language={{{ [get[type]else[text/vnd.tiddlywiki]] }}}/> + \ No newline at end of file diff --git a/editions/markdowndemo/tiddlywiki.info b/editions/markdowndemo/tiddlywiki.info index 39298101c..575c1e416 100644 --- a/editions/markdowndemo/tiddlywiki.info +++ b/editions/markdowndemo/tiddlywiki.info @@ -1,7 +1,9 @@ { "description": "Demo of the Markdown plugin", "plugins": [ - "tiddlywiki/markdown" + "tiddlywiki/markdown", + "tiddlywiki/highlight", + "tiddlywiki/katex" ], "themes": [ "tiddlywiki/vanilla", diff --git a/editions/pluginlibrary/tiddlywiki.info b/editions/pluginlibrary/tiddlywiki.info index 4f1ab1409..ba18ff0a2 100644 --- a/editions/pluginlibrary/tiddlywiki.info +++ b/editions/pluginlibrary/tiddlywiki.info @@ -17,8 +17,8 @@ ], "library": [ "--makelibrary","$:/UpgradeLibrary", - "--savelibrarytiddlers","$:/UpgradeLibrary","[prefix[$:/]] -[[$:/plugins/tiddlywiki/upgrade]] -[[$:/plugins/tiddlywiki/translators]] -[[$:/plugins/tiddlywiki/pluginlibrary]] -[[$:/plugins/tiddlywiki/jasmine]]","recipes/library/tiddlers/","$:/UpgradeLibrary/List", - "--savetiddler","$:/UpgradeLibrary/List","recipes/library/tiddlers.json", + "--savelibrarytiddlers","$:/UpgradeLibrary","[prefix[$:/]] -[[$:/plugins/tiddlywiki/upgrade]] -[[$:/plugins/tiddlywiki/translators]] -[[$:/plugins/tiddlywiki/pluginlibrary]] -[[$:/plugins/tiddlywiki/jasmine]]","recipes/library/tiddlers/","$:/UpgradeLibrary/List", + "--savetiddler","$:/UpgradeLibrary/List","recipes/library/tiddlers.json", "--rendertiddler","$:/plugins/tiddlywiki/pluginlibrary/library.template.html","index.html","text/plain"] } } diff --git a/editions/prerelease/tiddlers/$__StoryList.tid b/editions/prerelease/tiddlers/$__StoryList.tid deleted file mode 100644 index d1a1e959f..000000000 --- a/editions/prerelease/tiddlers/$__StoryList.tid +++ /dev/null @@ -1,5 +0,0 @@ -created: 20201222190149806 -list: [[Release 5.1.23]] -modified: 20201222190149806 -title: $:/StoryList -type: text/vnd.tiddlywiki \ No newline at end of file diff --git a/editions/prerelease/tiddlers/Release 5.3.4.tid b/editions/prerelease/tiddlers/Release 5.3.4.tid new file mode 100644 index 000000000..562909a93 --- /dev/null +++ b/editions/prerelease/tiddlers/Release 5.3.4.tid @@ -0,0 +1,61 @@ +caption: 5.3.4 +created: 20231223102229103 +modified: 20231223102229103 +tags: ReleaseNotes +title: Release 5.3.4 +type: text/vnd.tiddlywiki +description: Under development + +//[[See GitHub for detailed change history of this release|https://github.com/Jermolene/TiddlyWiki5/compare/v5.3.3...master]]// + +! Major Improvements + + +! Translation improvements + +Improvements to the following translations: + +* + +! Plugin Improvements + +* + +! Widget Improvements + +* + +! Usability Improvements + +* + +! Hackability Improvements + +* + +! Bug Fixes + +* + +! Node.js Improvements + +* + +! Performance Improvements + +* + +! Developer Improvements + +* + +! Infrastructure Improvements + +* + +! Acknowledgements + +[[@Jermolene|https://github.com/Jermolene]] would like to thank the contributors to this release who have generously given their time to help improve TiddlyWiki: + +<<.contributors """ +""">> diff --git a/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid b/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid index d8f641602..9f3972203 100644 --- a/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid +++ b/editions/prerelease/tiddlers/system/PrereleaseLocalPluginLibrary.tid @@ -1,6 +1,6 @@ title: $:/config/LocalPluginLibrary tags: $:/tags/PluginLibrary -url: http://127.0.0.1:8080/prerelease/library/v5.2.2/index.html +url: http://127.0.0.1:8080/prerelease/library/v5.3.2/index.html caption: {{$:/language/OfficialPluginLibrary}} (Prerelease Local) A locally installed version of the official ~TiddlyWiki plugin library at tiddlywiki.com for testing and debugging. //Requires a local web server to share the library// diff --git a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid index 88a007d50..d5cdcec63 100644 --- a/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid +++ b/editions/prerelease/tiddlers/system/PrereleaseOfficialPluginLibrary.tid @@ -1,6 +1,6 @@ title: $:/config/OfficialPluginLibrary tags: $:/tags/PluginLibrary -url: https://tiddlywiki.com/prerelease/library/v5.2.4/index.html +url: https://tiddlywiki.com/prerelease/library/v5.3.3/index.html caption: {{$:/language/OfficialPluginLibrary}} (Prerelease) The prerelease version of the official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team. diff --git a/editions/prerelease/tiddlers/system/TiddlyWiki Pre-release.tid b/editions/prerelease/tiddlers/system/TiddlyWiki Pre-release.tid index 7dd4e1f01..be4e4ff9b 100644 --- a/editions/prerelease/tiddlers/system/TiddlyWiki Pre-release.tid +++ b/editions/prerelease/tiddlers/system/TiddlyWiki Pre-release.tid @@ -1,7 +1,11 @@ title: TiddlyWiki Pre-release -modified: 20150428204930183 +modified: 20230731122156493 -This is a pre-release build of TiddlyWiki, [[also available in empty form|https://tiddlywiki.com/prerelease/empty.html]]. It is provided for testing purposes. ''Please don't try to use it for anything important'' -- you should use the latest official release from https://tiddlywiki.com. +This is a pre-release build of TiddlyWiki provided for testing and review purposes. ''Please don't try to depend on the pre-release for anything important'' -- you should use the latest official release from https://tiddlywiki.com. + +All of the changes in this pre-release are provisional until it is released and they become frozen by our backwards compatibility policies. This is the perfect time to raise questions or make suggestions. Please [[open a ticket at GitHub|https://github.com/Jermolene/TiddlyWiki5/issues/new/choose]] or make a post at https://talk.tiddlywiki.org/. + +The pre-release is also available as an [[empty wiki|https://tiddlywiki.com/prerelease/empty.html]] ready for reuse. <$list filter="[tag[ReleaseNotes]!has[released]!sort[created]]">
diff --git a/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid b/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid new file mode 100644 index 000000000..9a395abd6 --- /dev/null +++ b/editions/prerelease/tiddlers/system/configWikiParserRulesInlineWikilink.tid @@ -0,0 +1,3 @@ +title: $:/config/WikiParserRules/Inline/wikilink + +enable \ No newline at end of file diff --git a/editions/prerelease/tiddlers/system/favicon.ico b/editions/prerelease/tiddlers/system/favicon.ico deleted file mode 100644 index 707c67577..000000000 Binary files a/editions/prerelease/tiddlers/system/favicon.ico and /dev/null differ diff --git a/editions/prerelease/tiddlers/system/favicon.ico.meta b/editions/prerelease/tiddlers/system/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/prerelease/tiddlers/system/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/prerelease/tiddlers/system/favicon.png b/editions/prerelease/tiddlers/system/favicon.png new file mode 100644 index 000000000..bbf053e28 Binary files /dev/null and b/editions/prerelease/tiddlers/system/favicon.png differ diff --git a/editions/prerelease/tiddlers/system/favicon.png.meta b/editions/prerelease/tiddlers/system/favicon.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/prerelease/tiddlers/system/favicon.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid b/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid new file mode 100644 index 000000000..c4a164070 --- /dev/null +++ b/editions/prerelease/tiddlers/system/temp-my-scroll-position.tid @@ -0,0 +1,3 @@ +title: $:/my-scroll-position +scroll-left: 0 +scroll-top: 100 diff --git a/editions/prerelease/tiddlywiki.info b/editions/prerelease/tiddlywiki.info index 168fbb41f..c469dcf99 100644 --- a/editions/prerelease/tiddlywiki.info +++ b/editions/prerelease/tiddlywiki.info @@ -14,7 +14,10 @@ "tiddlywiki/dynannotate", "tiddlywiki/codemirror", "tiddlywiki/menubar", - "tiddlywiki/jszip" + "tiddlywiki/jszip", + "tiddlywiki/confetti", + "tiddlywiki/dynannotate", + "tiddlywiki/tour" ], "themes": [ "tiddlywiki/vanilla", diff --git a/editions/resumebuilder/tiddlers/documentation/Making a new section.tid b/editions/resumebuilder/tiddlers/documentation/Making a new section.tid index e787beb92..c6f81c8f7 100644 --- a/editions/resumebuilder/tiddlers/documentation/Making a new section.tid +++ b/editions/resumebuilder/tiddlers/documentation/Making a new section.tid @@ -15,7 +15,7 @@ You can have multiple template tiddlers that use the same input and options tidd !!Display tiddler -This is the container used to display the section in the résumé itself, there isn't any customization here. +This is the container used to display the section in the résumé itself, there isn't any customisation here. ''Required tags'': `Section Display`
''Required name format'': `$:/display/(section name) Display`
diff --git a/editions/resumebuilder/tiddlywiki.info b/editions/resumebuilder/tiddlywiki.info index 28f4ac3f3..c199c8cd7 100644 --- a/editions/resumebuilder/tiddlywiki.info +++ b/editions/resumebuilder/tiddlywiki.info @@ -20,4 +20,4 @@ "favicon": [ "--savetiddler","$:/favicon.ico","favicon.ico"] } -} \ No newline at end of file +} diff --git a/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid b/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid new file mode 100644 index 000000000..a1f1a0a27 --- /dev/null +++ b/editions/server-external-js/tiddlers/config/$__DefaultTiddlers.tid @@ -0,0 +1,7 @@ +created: 20230314153132081 +modified: 20230314153243008 +title: $:/DefaultTiddlers +type: text/vnd.tiddlywiki + +GettingStarted +[[Using the external JavaScript template]] diff --git a/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid b/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid new file mode 100644 index 000000000..071c85fe9 --- /dev/null +++ b/editions/server-external-js/tiddlers/config/$__config_SaveWikiButton_Filename.tid @@ -0,0 +1,4 @@ +title: $:/config/SaveWikiButton/Filename +type: text/vnd.tiddlywiki + +external-<>.html \ No newline at end of file diff --git a/editions/server-external-js/tiddlers/external/tiddlywiki.files b/editions/server-external-js/tiddlers/external/tiddlywiki.files new file mode 100644 index 000000000..73474d2ce --- /dev/null +++ b/editions/server-external-js/tiddlers/external/tiddlywiki.files @@ -0,0 +1,8 @@ +{ + "tiddlers": [ + { + "file": "../../../tw5.com/tiddlers/webserver/Using the external JavaScript template.tid", + "isTiddlerFile": true + } + ] +} \ No newline at end of file diff --git a/editions/server-external-js/tiddlywiki.info b/editions/server-external-js/tiddlywiki.info index 96c03babd..b0c245b49 100644 --- a/editions/server-external-js/tiddlywiki.info +++ b/editions/server-external-js/tiddlywiki.info @@ -2,8 +2,7 @@ "description": "Client-server edition with external tiddlywiki.js", "plugins": [ "tiddlywiki/tiddlyweb", - "tiddlywiki/filesystem", - "tiddlywiki/highlight" + "tiddlywiki/filesystem" ], "themes": [ "tiddlywiki/vanilla", @@ -13,13 +12,13 @@ "listen": [ "--listen","root-tiddler=$:/core/save/all-external-js","use-browser-cache=yes"], "index": [ - "--rendertiddler","$:/core/save/offline-external-js","index.html","text/plain", + "--render","$:/core/save/offline-external-js","[[external-]addsuffixaddsuffix[.html]]","text/plain", "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"], + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"], "tiddlywikicore": [ "--render","$:/core/templates/tiddlywiki5.js","[[tiddlywikicore-]addsuffixaddsuffix[.js]]","text/plain"] } diff --git a/editions/server/tiddlywiki.info b/editions/server/tiddlywiki.info index a9a3ed3bd..e35ff95f8 100644 --- a/editions/server/tiddlywiki.info +++ b/editions/server/tiddlywiki.info @@ -11,11 +11,11 @@ ], "build": { "index": [ - "--rendertiddler","$:/plugins/tiddlywiki/tiddlyweb/save/offline","index.html","text/plain"], + "--render","$:/plugins/tiddlywiki/tiddlyweb/save/offline","index.html","text/plain"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"] } } \ No newline at end of file diff --git a/editions/test/playwright.spec.js b/editions/test/playwright.spec.js new file mode 100644 index 000000000..1d8c624c7 --- /dev/null +++ b/editions/test/playwright.spec.js @@ -0,0 +1,25 @@ +const { test, expect } = require('@playwright/test'); +const {resolve} = require('path'); + +const indexPath = resolve(__dirname, 'output', 'test.html'); +const crossPlatformIndexPath = indexPath.replace(/^\/+/, ''); + + +test('get started link', async ({ page }) => { + // The tests can take a while to run + const timeout = 1000 * 30; + test.setTimeout(timeout); + + // Load the generated test TW html + await page.goto(`file:///${crossPlatformIndexPath}`); + + // Sanity check + await expect(page.locator('.tc-site-title'), "Expected correct page title to verify the test page was loaded").toHaveText('TiddlyWiki5'); + + // Wait for jasmine results bar to appear + await expect(page.locator('.jasmine-overall-result'), "Expected jasmine test results bar to be present").toBeVisible({timeout}); + + // Assert the tests have passed + await expect(page.locator('.jasmine-overall-result.jasmine-failed'), "Expected jasmine tests to not have failed").not.toBeVisible(); + await expect(page.locator('.jasmine-overall-result.jasmine-passed'), "Expected jasmine tests to have passed").toBeVisible(); +}); diff --git a/editions/test/tiddlers/tests/data/conditionals/Basic.tid b/editions/test/tiddlers/tests/data/conditionals/Basic.tid new file mode 100644 index 000000000..ff2d2df4d --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/Basic.tid @@ -0,0 +1,26 @@ +title: Conditionals/Basic +description: Basic conditional shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Text + +This is a <% if [match[one]] %>Elephant<% endif %>, I think. ++ +title: Output + +<$let something="one"> +{{Text}} + + +<$let something="two"> +{{Text}} + ++ +title: ExpectedResult + +

+This is a Elephant, I think. +

+This is a , I think. +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/BlockMode.tid b/editions/test/tiddlers/tests/data/conditionals/BlockMode.tid new file mode 100644 index 000000000..45233baa4 --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/BlockMode.tid @@ -0,0 +1,37 @@ +title: Conditionals/BlockMode +description: Basic conditional shortcut syntax in block mode +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure test(animal) +<% if [match[Elephant]] %> + +! It is an elephant + +<% else %> + +<% if [match[Giraffe]] %> + +! It is a giraffe + +<% else %> + +! It is completely unknown + +<% endif %> + +<% endif %> + +\end + +<> + +<> + +<> ++ +title: ExpectedResult + +

It is a giraffe

It is an elephant

It is completely unknown

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/Else.tid b/editions/test/tiddlers/tests/data/conditionals/Else.tid new file mode 100644 index 000000000..7bc32b34e --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/Else.tid @@ -0,0 +1,26 @@ +title: Conditionals/Else +description: Else conditional shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Text + +This is a <% if [match[one]] %>Elephant<% else %>Crocodile<% endif %>, I think. ++ +title: Output + +<$let something="one"> +{{Text}} + + +<$let something="two"> +{{Text}} + ++ +title: ExpectedResult + +

+This is a Elephant, I think. +

+This is a Crocodile, I think. +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/Elseif.tid b/editions/test/tiddlers/tests/data/conditionals/Elseif.tid new file mode 100644 index 000000000..d37f3380c --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/Elseif.tid @@ -0,0 +1,32 @@ +title: Conditionals/Elseif +description: Elseif conditional shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Text + +This is a <% if [match[one]] %>Elephant<% elseif [match[two]] %>Antelope<% else %>Crocodile<% endif %>, I think. ++ +title: Output + +<$let something="one"> +{{Text}} + + +<$let something="two"> +{{Text}} + + +<$let something="three"> +{{Text}} + ++ +title: ExpectedResult + +

+This is a Elephant, I think. +

+This is a Antelope, I think. +

+This is a Crocodile, I think. +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/MissingEndIf.tid b/editions/test/tiddlers/tests/data/conditionals/MissingEndIf.tid new file mode 100644 index 000000000..cacaf9869 --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/MissingEndIf.tid @@ -0,0 +1,26 @@ +title: Conditionals/MissingEndif +description: Conditional shortcut syntax with missing endif +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Text + +This is a <% if [match[one]] %>Elephant ++ +title: Output + +<$let something="one"> +{{Text}} + + +<$let something="two"> +{{Text}} + ++ +title: ExpectedResult + +

+This is a Elephant +

+This is a +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/MultipleResults.tid b/editions/test/tiddlers/tests/data/conditionals/MultipleResults.tid new file mode 100644 index 000000000..baa966ed5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/MultipleResults.tid @@ -0,0 +1,12 @@ +title: Conditionals/MultipleResults +description: Check that multiple results from the filter are ignored +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +This is a <% if 1 2 3 4 5 6 %>Elephant<% endif %>, I think. ++ +title: ExpectedResult + +

This is a Elephant, I think.

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/conditionals/Nested.tid b/editions/test/tiddlers/tests/data/conditionals/Nested.tid new file mode 100644 index 000000000..dffa791fc --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/Nested.tid @@ -0,0 +1,38 @@ +title: Conditionals/Nested +description: Nested conditional shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure test(animal) +<% if [match[Elephant]] %> +It is an elephant +<% else %> +<% if [match[Giraffe]] %> +It is a giraffe +<% else %> +It is completely unknown +<% endif %> +<% endif %> +\end + +<> + +<> + +<> + ++ +title: ExpectedResult + + + +It is a giraffe + + +It is an elephant + + +It is completely unknown + diff --git a/editions/test/tiddlers/tests/data/conditionals/NestedElseif.tid b/editions/test/tiddlers/tests/data/conditionals/NestedElseif.tid new file mode 100644 index 000000000..6fba8cac8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/conditionals/NestedElseif.tid @@ -0,0 +1,60 @@ +title: Conditionals/NestedElseif +description: Nested elseif conditional shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Text + +\whitespace trim +This is a + <% if [match[one]] %> + <% if [match[one]] %> + Indian + <% elseif [match[two]] %> + African + <% else %> + Unknown + <% endif %> + Elephant + <% elseif [match[two]] %> + Antelope + <% else %> + Crocodile + <% endif %> +, I think. ++ +title: Output + +<$let something="one" another="one"> +{{Text}} + + +<$let something="one" another="two"> +{{Text}} + + +<$let something="one" another="three"> +{{Text}} + + +<$let something="two"> +{{Text}} + + +<$let something="three"> +{{Text}} + ++ +title: ExpectedResult + +

+This is a Indian Elephant, I think. +

+This is a African Elephant, I think. +

+This is a Unknown Elephant, I think. +

+This is a Antelope, I think. +

+This is a Crocodile, I think. +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid new file mode 100644 index 000000000..3e4d610d0 --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/NestedParameterised.tid @@ -0,0 +1,24 @@ +title: CustomOperators/NestedParameterised +description: Nested parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(first:ignored,factor:0.5) +[divide[2]multiply] +\end + +\function .multiplebysomething(first:ignored,factor:2) +[multiply[2].dividebysomething[],] +\end + +<$text text={{{ [[123].multiplebysomething[]] }}}/> +- +<$text text={{{ [[123].multiplebysomething[x],[4]] }}}/> + ++ +title: ExpectedResult + +

246-492

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid new file mode 100644 index 000000000..2f8337b0f --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Parameterised.tid @@ -0,0 +1,24 @@ +title: CustomOperators/Parameterised +description: Parameterised custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .multiplybysomething(first:ignored,factor:2) +[multiply[2]multiply] +\end + +<$text text={{{ [[123].multiplybysomething[]] }}}/> +- +<$text text={{{ [[123].multiplybysomething[x],[4]] }}}/> +| +<$text text={{{ [[123]function[.multiplybysomething]] }}}/> +- +<$text text={{{ [[123]function[.multiplybysomething],[x],[4]] }}}/> + ++ +title: ExpectedResult + +

492-984|492-984

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/custom-operators/Simple.tid b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid new file mode 100644 index 000000000..089701295 --- /dev/null +++ b/editions/test/tiddlers/tests/data/custom-operators/Simple.tid @@ -0,0 +1,21 @@ +title: CustomOperators/Simple +description: Simple custom operator usage +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\function .multiplybytwo() +[multiply[2]] +\end + +<$text text={{{ [[123].multiplybytwo[]] }}}/> +| +<$text text={{{ [[123]function[.multiplybytwo]] }}}/> + ++ +title: ExpectedResult + +

246|246

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/deserializers/case 6.tid b/editions/test/tiddlers/tests/data/deserializers/case 6.tid new file mode 100644 index 000000000..b6e653c39 --- /dev/null +++ b/editions/test/tiddlers/tests/data/deserializers/case 6.tid @@ -0,0 +1,8 @@ +title: dezerializer test data case 6 +type: application/json + +[ + {"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\n\n","title":"GettingStarted","modified":"20230601125601619"}, + {"created":"20230601125507054","text":"Welcome to \"TiddlyWiki\".\n\nThis is a test tiddler.","tags":"","title":"Hello There \"Welcome\"","modified":"20230601125551144"}, + {"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\n\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."} +] diff --git a/editions/test/tiddlers/tests/data/filters/Base64.tid b/editions/test/tiddlers/tests/data/filters/Base64.tid new file mode 100644 index 000000000..17f1defff --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/Base64.tid @@ -0,0 +1,19 @@ +title: Filters/Base64 +description: Test {encode|decode}base64 operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +(<$text text={{{ [[Jeremy1234]encodebase64[]] }}}/>) +(<$text text={{{ [[]encodebase64[]] }}}/>) +(<$text text={{{ [[SmVyZW15MTIzNA==]decodebase64[]] }}}/>) +(<$text text={{{ [[]decodebase64[]] }}}/>) ++ +title: ExpectedResult + +

(SmVyZW15MTIzNA==) +() +(Jeremy1234) +()

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid new file mode 100644 index 000000000..e6e519df5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch1.tid @@ -0,0 +1,28 @@ +title: Filters/DiffMergePatch1 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define text2() +the hat saw in every category +\end + +<$text text={{{ [makepatches] }}}/> ++ +title: ExpectedResult + +

@@ -1,22 +1,29 @@ + the +-c ++h + at sa +-t on the mat ++w in every category +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid new file mode 100644 index 000000000..1fa355573 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch2.tid @@ -0,0 +1,25 @@ +title: Filters/DiffMergePatch2 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define text2() +the hat saw in every category +\end + +<$let patches={{{ [makepatches] }}}> + +<$text text={{{ [applypatches] }}}/> + + ++ +title: ExpectedResult + +the hat saw in every category \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid b/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid new file mode 100644 index 000000000..87d98e890 --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/DiffMergePatch3.tid @@ -0,0 +1,22 @@ +title: Filters/DiffMergePatch3 +description: Tests for diff-merge-patch derived operators +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define text1() +the cat sat on the mat +\end + +\define patches() +**NOT A VALID PATCH** +\end + +<$text text={{{ [applypatches] }}}/> + ++ +title: ExpectedResult + +the cat sat on the mat \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/filters/substitute.tid b/editions/test/tiddlers/tests/data/filters/substitute.tid new file mode 100644 index 000000000..873d8e0ba --- /dev/null +++ b/editions/test/tiddlers/tests/data/filters/substitute.tid @@ -0,0 +1,40 @@ +title: Filters/substitute +description: Test substitute operator +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: substitute filter data 1 +tags: Hello There [[Welcome to TiddlyWiki]] GettingStarted + +TiddlyWiki ++ +title: substitute filter data 2 + +The output of the filter `[[substitute filter data 1]tags[]]` is ${[[substitute filter data 1]tags[]]}$. ++ +title: substitute filter data 3 + +Welcome to $(projectname)$ $1$ $2$ $3$. Tiddlers starting with `substitute`: ${[prefix[substitute]format:titlelist[]join[ ]]}$. ++ +title: Output + +\whitespace trim +<$let projectname="TiddlyWiki"> +(<$text text={{{ [[]substitute[]] }}}/>) +(<$text text={{{ [[Hello There, welcome to $TiddlyWiki$]substitute[]] }}}/>) +(<$text text={{{ [[Welcome to $(projectname)$]substitute[]] }}}/>) +(<$text text={{{ [[Welcome to $(projectname)$ $1$]substitute[today]] }}}/>) +(<$text text={{{ [[This is not a valid embedded filter ${ hello )$]substitute[]] }}}/>) +(<$text text={{{ [{substitute filter data 2}substitute[]] }}}/>) +(<$text text={{{ [{substitute filter data 3}substitute[every],[day]] }}}/>) + ++ +title: ExpectedResult + +

() +(Hello There, welcome to $TiddlyWiki$) +(Welcome to TiddlyWiki) +(Welcome to TiddlyWiki today) +(This is not a valid embedded filter ${ hello )$) +(The output of the filter `[[substitute filter data 1]tags[]]` is Hello.) +(Welcome to TiddlyWiki every day $3$. Tiddlers starting with `substitute`: [[substitute filter data 1]] [[substitute filter data 2]] [[substitute filter data 3]].)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid b/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid new file mode 100644 index 000000000..2deb49bdc --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionAttributes.tid @@ -0,0 +1,24 @@ +title: Functions/FunctionAttributes +description: Attributes specified as function invocations +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(factor:0.5) +[divide] +\end + +\function multiplebysomething(first:ignored,factor:2) +[multiply[2].dividebysomething[0.25]] +\end + +<$text text=<>/> +| +<$text text=<>/> + ++ +title: ExpectedResult + +

16|32

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables.tid b/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables.tid new file mode 100644 index 000000000..5226e9f05 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables.tid @@ -0,0 +1,24 @@ +title: Functions/FunctionFilterrunVariables +description: Functions in filter runs that set variables +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Idiosyncrasy +caption: Idiosyncrasy Caption Field + ++ +title: Output + +\whitespace trim +\procedure demo-subfilter() [] +\function .demo-function() [] + +<$let currentTiddler="Idiosyncrasy"> +<$text text={{{ [get[caption]!is[blank]else] :map[subfilter] }}}/>, +<$text text={{{ [get[caption]!is[blank]else] :map[.demo-function[]] }}}/> + + ++ +title: ExpectedResult + +

Idiosyncrasy Caption Field,Idiosyncrasy Caption Field

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables2.tid b/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables2.tid new file mode 100644 index 000000000..07b8c412a --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionFilterrunVariables2.tid @@ -0,0 +1,20 @@ +title: Functions/FunctionFilterrunVariables2 +description: Functions in filter runs that set variables +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Apple +cost: 5 + ++ +title: Output + +\whitespace trim +\function .doublecost() [get[cost]multiply[2]] + +<$text text={{{ [[Apple]] :map[.doublecost[]] }}}/> + ++ +title: ExpectedResult + +10 \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid b/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid new file mode 100644 index 000000000..e2a0038dc --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/FunctionOperator.tid @@ -0,0 +1,24 @@ +title: Functions/FunctionOperator +description: Calling a function via the function operator +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .dividebysomething(factor:0.5) +[divide] +\end + +\function multiplebysomething(first:ignored,factor:2) +[multiplymultiply[2].dividebysomething[0.25]] +\end + +<$text text={{{ [[4]function[multiplebysomething]] }}}/> +| +<$text text={{{ [[6]function[multiplebysomething],[ignored],[4]] }}}/> + ++ +title: ExpectedResult + +

64|192

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/IndentedFunctions.tid b/editions/test/tiddlers/tests/data/functions/IndentedFunctions.tid new file mode 100644 index 000000000..206a8958e --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/IndentedFunctions.tid @@ -0,0 +1,24 @@ +title: Functions/Function/Indented +description: Indented function definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + + \whitespace trim + \function .dividebysomething(factor:0.5) + [divide] + \end + + \function multiplebysomething(first:ignored,factor:2) + [multiplymultiply[2].dividebysomething[0.25]] + \end + +<$text text={{{ [[4]function[multiplebysomething]] }}}/> +| +<$text text={{{ [[6]function[multiplebysomething],[ignored],[4]] }}}/> + ++ +title: ExpectedResult + +

64|192

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/MissingFunction.tid b/editions/test/tiddlers/tests/data/functions/MissingFunction.tid new file mode 100644 index 000000000..25498e452 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/MissingFunction.tid @@ -0,0 +1,15 @@ +title: Functions/MissingFunction +description: Calling a missing function via the function operator +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$text text={{{ [[23]function[missing]] }}}/> + ++ +title: ExpectedResult + +23 \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid b/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid new file mode 100644 index 000000000..81be22f16 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/RunawayRecursiveFunctions.tid @@ -0,0 +1,18 @@ +title: Functions/RunawayRecursiveFunctions +description: Runaway recursive functions +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function .buffalo(p) +[.buffalo

] +\end + +<$text text=<<.buffalo 8>>/> + ++ +title: ExpectedResult + +/**-- Excessive filter recursion --**/ \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid b/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid new file mode 100644 index 000000000..8a2b0a91a --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/UndefinedParameters.tid @@ -0,0 +1,22 @@ +title: Functions/UndefinedParameters +description: Undefined function parameters +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\function greet(who) +[[hello ]addsuffix] +\end + +<$text text={{{[function[greet],[world]]}}}/> + +<> + +<$text text={{{[function[greet]]}}}/> + +<> ++ +title: ExpectedResult + +hello world

hello world

hello

hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid b/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid new file mode 100644 index 000000000..36b64e4a3 --- /dev/null +++ b/editions/test/tiddlers/tests/data/functions/WikifiedFunctions.tid @@ -0,0 +1,36 @@ +title: Functions/WikifiedFunctions +description: Wikified functions +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function fn-buffalo(param) +[addsuffix[ with a ''buffalo'']] +\end + +\procedure proc-buffalo(param) +<> with a ''buffalo'' +\end + +\define macro-buffalo(param) +$param$ with a ''buffalo'' +\end + +<> + +<> + +<> + +<$transclude $variable="fn-buffalo" param="Going to lunch" $output="text/plain"/> + +<$transclude $variable="proc-buffalo" param="Going to breakfast" $output="text/plain"/> + +<$transclude $variable="macro-buffalo" param="Going to dinner" $output="text/plain"/> + ++ +title: ExpectedResult + +

Going to lunch with a ''buffalo''

Going to breakfastwith abuffalo

Going to dinner with a buffalo

Going to lunch with a ''buffalo''Going to breakfastwith abuffaloGoing to dinner with a buffalo \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/genesis-widget/Block.tid b/editions/test/tiddlers/tests/data/genesis-widget/Block.tid new file mode 100644 index 000000000..dfa5dacaf --- /dev/null +++ b/editions/test/tiddlers/tests/data/genesis-widget/Block.tid @@ -0,0 +1,30 @@ +title: Genesis/Block +description: genesis widget distinguishes between block and inline +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$genesis $type="$reveal" type=nomatch> + +Block + + +<$genesis $type="$reveal" type=nomatch $mode=block> + +Block forced block + + +<$genesis $type="$reveal" type=nomatch $mode=inline> + +Block forced inline + + +<$genesis $type=$reveal type=nomatch>Inline +<$genesis $type=$reveal type=nomatch $mode=block>Inline forced block +<$genesis $type=$reveal type=nomatch $mode=inline>Inline forced inline ++ +title: ExpectedResult + +

Block

Block forced block

Block forced inline

Inline

Inline forced block
Inline forced inline

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/genesis-widget/EmptyType.tid b/editions/test/tiddlers/tests/data/genesis-widget/EmptyType.tid new file mode 100644 index 000000000..59768aa0c --- /dev/null +++ b/editions/test/tiddlers/tests/data/genesis-widget/EmptyType.tid @@ -0,0 +1,14 @@ +title: Genesis/EmptyType +description: Using an empty type attribute with the genesis widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +<$genesis>Mouse + +<$genesis $type="">Mouse ++ +title: ExpectedResult + +

Mouse

Mouse

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid b/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid new file mode 100644 index 000000000..f6834998d --- /dev/null +++ b/editions/test/tiddlers/tests/data/genesis-widget/RedefineLet.tid @@ -0,0 +1,31 @@ +title: Genesis/RedefineLet +description: Using the genesis widget to override the let widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $let() +\whitespace trim +<$parameters $params="@params"> +<$setmultiplevariables $names="[<@params>jsonindexes[]]" $values="[<@params>jsonindexes[]] :map[<@params>jsongetaddprefix[--]addsuffix[--]]"> +<$slot $name="ts-raw"/> + + +\end +<$let + one="Elephant" + $two="Kangaroo" + $$three="Giraffe" +> +(<$text text=<>/>) +(<$text text=<<$two>>/>) +(<$text text=<<$$three>>/>) + ++ +title: ExpectedResult + +

(--Elephant--) +(--Kangaroo--) +(--Giraffe--)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid new file mode 100644 index 000000000..5d351583e --- /dev/null +++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets.tid @@ -0,0 +1,23 @@ +title: ImportVariables/WithSetWidgets +description: Import variables defined with a set widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definitions +<$text text=<>/>, +<$text text=<>/> ++ +title: Definitions + +\whitespace trim +<$set name="one" value="elephant"> +<$set name="two" value="giraffe"> + + ++ +title: ExpectedResult + +

elephant,giraffe

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid new file mode 100644 index 000000000..23fa58c57 --- /dev/null +++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgets2.tid @@ -0,0 +1,22 @@ +title: ImportVariables/WithSetWidgets2 +description: Import variables defined with a set widget without whitespace pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definitions +<$text text=<>/>, +<$text text=<>/> ++ +title: Definitions + +<$set name="one" value="elephant"> +<$set name="two" value="giraffe"> + + ++ +title: ExpectedResult + +

elephant,giraffe

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid new file mode 100644 index 000000000..eaa81f38c --- /dev/null +++ b/editions/test/tiddlers/tests/data/importvariables/WithSetWidgetsAndMacros.tid @@ -0,0 +1,29 @@ +title: ImportVariables/WithSetWidgetsAndMacros +description: Import variables defined with a set widget without whitespace pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definitions +<$text text=<>/>, +<$text text=<
>/>, +<$text text=<>/>, +<$text text=<>/> ++ +title: Definitions + +\define name() Bugs Bunny +\procedure address() +Bunny Hill +\end + +<$set name="one" value="elephant"> +<$set name="two" value="giraffe"> + + ++ +title: ExpectedResult + +

Bugs Bunny,Bunny Hill,elephant,giraffe

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithEmptyParagraphTemplate.tid b/editions/test/tiddlers/tests/data/list-widget/WithEmptyParagraphTemplate.tid new file mode 100644 index 000000000..7730f525a --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithEmptyParagraphTemplate.tid @@ -0,0 +1,13 @@ +title: ListWidget/WithEmptyParagraphTemplate +description: List widget with an empty paragraph as inline template +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +<$list filter="1">

++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplates.tid b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplates.tid new file mode 100644 index 000000000..aad322f54 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplates.tid @@ -0,0 +1,29 @@ +title: ListWidget/WithExplicitTemplates +description: List widget with explicit templates +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + <$list-template> + <$text text=<>/> + + <$list-empty> + None! + + +\end + +<> + +<> + ++ +title: ExpectedResult + +

123

None!

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesInBlockMode.tid b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesInBlockMode.tid new file mode 100644 index 000000000..8e61c2e24 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesInBlockMode.tid @@ -0,0 +1,32 @@ +title: ListWidget/WithExplicitTemplatesInBlockMode +description: List widget with explicit templates in block mode +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + + <$list-template> + <$text text=<>/> + + + <$list-empty> + None! + + + +\end + +<> + +<> + ++ +title: ExpectedResult + +123None! \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesOverriddenByAttributes.tid b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesOverriddenByAttributes.tid new file mode 100644 index 000000000..0ce5780af --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithExplicitTemplatesOverriddenByAttributes.tid @@ -0,0 +1,33 @@ +title: ListWidget/WithExplicitTemplatesOverriddenByAttributes +description: List widget with explicit templates +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<> emptyMessage="Zero" template="Template"> + <$list-template> + <$text text=<>/> + + <$list-empty> + None! + + +\end + +<> + +<> + ++ +title: Template + +<$text text=<>/><$text text=<>/> ++ +title: ExpectedResult + +

112233

Zero

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid new file mode 100644 index 000000000..f1b6f25e9 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplate.tid @@ -0,0 +1,30 @@ +title: ListWidget/WithJoinTemplate +description: List widget with join template and $list-empty +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + Item:<> + + <$list-empty> + None! + + + <$list-join>, + +\end + +<> + +<> + ++ +title: ExpectedResult + +

Item:1,Item:2,Item:3

None!

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid new file mode 100644 index 000000000..c12f4c801 --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithJoinTemplateInBlockMode.tid @@ -0,0 +1,32 @@ +title: ListWidget/WithJoinTemplateInBlockMode +description: List widget with join template and $list-empty in block mode +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + + Item:<> + + <$list-empty> + None! + + + <$list-join>
+ +\end + +<> + +<> + ++ +title: ExpectedResult +comment: I wish there was a good way to get rid of these extraneous paragraph elements + +

Item:1


Item:2


Item:3

None! \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithLimit.tid b/editions/test/tiddlers/tests/data/list-widget/WithLimit.tid new file mode 100644 index 000000000..2f630a1dc --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithLimit.tid @@ -0,0 +1,25 @@ +title: ListWidget/WithLimit +description: List widget with limit +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +Zero: <$list filter="1 2 3 4" limit="0" template="Template"/> + +One: <$list filter="1 2 3 4" limit="1" template="Template"/> + +Two: <$list filter="1 2 3 4" limit="2" template="Template"/> + +Minus Two: <$list filter="1 2 3 4" limit="-2" template="Template"/> + ++ +title: Template + +<$text text=<>/> ++ +title: ExpectedResult + +

Zero:

One: 1

Two: 12

Minus Two: 34 +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/list-widget/WithMissingTemplate.tid b/editions/test/tiddlers/tests/data/list-widget/WithMissingTemplate.tid new file mode 100644 index 000000000..40fb2f07b --- /dev/null +++ b/editions/test/tiddlers/tests/data/list-widget/WithMissingTemplate.tid @@ -0,0 +1,26 @@ +title: ListWidget/WithMissingTemplate +description: List widget with explicit templates +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + ++ +title: Output + +\whitespace trim + +\procedure test(filter) +<$list filter=<>> + <$list-empty> + None! + + +\end + +<> + +<> + ++ +title: ExpectedResult + +

123

None!

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/EndInBody.tid b/editions/test/tiddlers/tests/data/macros/EndInBody.tid new file mode 100644 index 000000000..e93a0917d --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/EndInBody.tid @@ -0,0 +1,16 @@ +title: Macros/EndInBody +description: \end line starting with non-whitespace is part of macro body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define hello() + hello \end +\end + +Out: <> ++ +title: ExpectedResult + +

Out: hello \end

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/IndentedEnd.tid b/editions/test/tiddlers/tests/data/macros/IndentedEnd.tid new file mode 100644 index 000000000..97f2c4197 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/IndentedEnd.tid @@ -0,0 +1,16 @@ +title: Macros/IndentedEnd +description: \end line starting with whitespace ends a macro body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define hello() + hello \end + \end + +Out: <> ++ +title: ExpectedResult + +

Out: hello \end

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/MismatchedNamedEnd.tid b/editions/test/tiddlers/tests/data/macros/MismatchedNamedEnd.tid new file mode 100644 index 000000000..b66821753 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/MismatchedNamedEnd.tid @@ -0,0 +1,16 @@ +title: Macros/MismatchedNamedEnd +description: Mismatched named end is part of the body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define hello() + \end goodbye +\end + +Out: <> ++ +title: ExpectedResult + +

Out: \end goodbye

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd.tid b/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd.tid new file mode 100644 index 000000000..6998672ba --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd.tid @@ -0,0 +1,18 @@ +title: Macros/WhitespaceOnlyWithEnd +description: The /end should be detected when macro definition contains only whitespace +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define max() +\end +Nothing +\end + +Out: <> ++ +title: ExpectedResult + +

Nothing +\end

Out:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd2.tid b/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd2.tid new file mode 100644 index 000000000..60db278d6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/WhitespaceOnlyWithEnd2.tid @@ -0,0 +1,15 @@ +title: Macros/WhitespaceOnlyWithEnd2 +description: Line with \end can start with whitespace +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define empty() + \end + +Out: <> ++ +title: ExpectedResult + +

Out:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented.tid b/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented.tid new file mode 100644 index 000000000..e040deaf7 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented.tid @@ -0,0 +1,36 @@ +title: Macros/NestedMacros-indented +description: Nested Macros-indented +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\define outer() + \whitespace trim + + \define middle() + \whitespace trim + + \define inner() + \whitespace trim + + Jaguar + + \end inner + + <> + + \end middle + + <> + +\end outer + +<> + ++ +title: ExpectedResult + +

Jaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented2.tid b/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented2.tid new file mode 100644 index 000000000..36a3cc8a3 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros-indented2.tid @@ -0,0 +1,36 @@ +title: Macros/NestedMacros-indented2 +description: Nested Macros-indented with spaces +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\define outer() + \whitespace trim + + \define middle() + \whitespace trim + + \define inner() + \whitespace trim + + Jaguar + + \end inner + + <> + + \end middle + + <> + +\end outer + +<> + ++ +title: ExpectedResult + +

Jaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/macros/NestedMacros.tid b/editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros.tid similarity index 100% rename from editions/test/tiddlers/tests/data/macros/NestedMacros.tid rename to editions/test/tiddlers/tests/data/macros/nested-macros/NestedMacros.tid diff --git a/editions/test/tiddlers/tests/data/macros/trailing-newlines/TrailingNewlines.tid b/editions/test/tiddlers/tests/data/macros/trailing-newlines/TrailingNewlines.tid new file mode 100644 index 000000000..18037fac2 --- /dev/null +++ b/editions/test/tiddlers/tests/data/macros/trailing-newlines/TrailingNewlines.tid @@ -0,0 +1,22 @@ +title: Macros/TrailingNewlines +description: Trailing newlines in macros must not be dropped +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\define inner() +Paragraph 1 + +Paragraph 2 +\end +\define outer() +<$macrocall $name=inner /> + +\end +<> + ++ +title: ExpectedResult + +

Paragraph 1

Paragraph 2

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/CustomTitle.tid b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/CustomTitle.tid new file mode 100644 index 000000000..2c7b8ba05 --- /dev/null +++ b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/CustomTitle.tid @@ -0,0 +1,35 @@ +title: Message/tm-import-tiddlers/CustomTitle +description: tm-import-tiddlers message can import to a tiddler with a custom title +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +text: <$text text={{MyCustomTitle}}/> +plugin-type: <$text text={{MyCustomTitle!!plugin-type}}/> +~$:/StoryList: <$text text={{$:/StoryList!!list}}/> ++ +title: Actions + +<$navigator story="$:/StoryList"> +<$action-sendmessage + $message="tm-import-tiddlers" + $param='[{"title": "Elephants"}, {"title": "Eagles"}]' + importTitle=MyCustomTitle/> + + ++ +title: ExpectedResult + +

text: { + "tiddlers": { + "Elephants": { + "title": "Elephants" + }, + "Eagles": { + "title": "Eagles" + } + } +} +plugin-type: import +$:/StoryList: MyCustomTitle

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpen.tid b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpen.tid new file mode 100644 index 000000000..cc2c3673a --- /dev/null +++ b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpen.tid @@ -0,0 +1,35 @@ +title: Message/tm-import-tiddlers/NoAutoOpen +description: tm-import-tiddlers can import without automatically opening the import tiddler +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +text: <$text text={{$:/Import}}/> +plugin-type: <$text text={{$:/Import!!plugin-type}}/> +~$:/StoryList: <$text text={{$:/StoryList!!list}}/> ++ +title: Actions + +<$navigator story="$:/StoryList"> +<$action-sendmessage + $message="tm-import-tiddlers" + $param='[{"title": "Elephants"}, {"title": "Eagles"}]' + autoOpenOnImport=no/> + + ++ +title: ExpectedResult + +

text: { + "tiddlers": { + "Elephants": { + "title": "Elephants" + }, + "Eagles": { + "title": "Eagles" + } + } +} +plugin-type: import +$:/StoryList:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpenViaVar.tid b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpenViaVar.tid new file mode 100644 index 000000000..6970131f1 --- /dev/null +++ b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/NoAutoOpenViaVar.tid @@ -0,0 +1,36 @@ +title: Message/tm-import-tiddlers/NoAutoOpenViaVar +description: tm-import-tiddlers can import and open based on tv-auto-open-on-import +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +text: <$text text={{$:/Import}}/> +plugin-type: <$text text={{$:/Import!!plugin-type}}/> +~$:/StoryList: <$text text={{$:/StoryList!!list}}/> ++ +title: Actions + +<$let tv-auto-open-on-import="no"> +<$navigator story="$:/StoryList"> +<$action-sendmessage + $message="tm-import-tiddlers" + $param='[{"title": "Elephants"}, {"title": "Eagles"}]'/> + + + ++ +title: ExpectedResult + +

text: { + "tiddlers": { + "Elephants": { + "title": "Elephants" + }, + "Eagles": { + "title": "Eagles" + } + } +} +plugin-type: import +$:/StoryList:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/default.tid b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/default.tid new file mode 100644 index 000000000..715a763f4 --- /dev/null +++ b/editions/test/tiddlers/tests/data/messages/tm-import-tiddler/default.tid @@ -0,0 +1,34 @@ +title: Message/tm-import-tiddlers/default +description: tm-import-tiddlers message by default should import to $:/Import and open the tiddler +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +text: <$text text={{$:/Import}}/> +plugin-type: <$text text={{$:/Import!!plugin-type}}/> +~$:/StoryList: <$text text={{$:/StoryList!!list}}/> ++ +title: Actions + +<$navigator story="$:/StoryList"> +<$action-sendmessage + $message="tm-import-tiddlers" + $param='[{"title": "Elephants"}, {"title": "Eagles"}]'/> + + ++ +title: ExpectedResult + +

text: { + "tiddlers": { + "Elephants": { + "title": "Elephants" + }, + "Eagles": { + "title": "Eagles" + } + } +} +plugin-type: import +$:/StoryList: $:/Import

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/pragmas/Parsermode-indented.tid b/editions/test/tiddlers/tests/data/pragmas/Parsermode-indented.tid new file mode 100644 index 000000000..10747735f --- /dev/null +++ b/editions/test/tiddlers/tests/data/pragmas/Parsermode-indented.tid @@ -0,0 +1,36 @@ +title: Pragmas/Parsermode-indented +description: parsermode pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +{{AlwaysInline}} + +{{AlwaysBlock}} + +{{AlwaysInline}}{{AlwaysBlock}} + ++ +title: AlwaysInline + + \parsermode inline +! Not Heading + +Text with ''bold'' ++ +title: AlwaysBlock + + \parsermode block +! Heading + +Text with ''bold'' ++ +title: ExpectedResult + +! Not Heading + +Text with bold

Heading

Text with bold

! Not Heading + +Text with bold

Heading

Text with bold

+

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid b/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid new file mode 100644 index 000000000..57869e37a --- /dev/null +++ b/editions/test/tiddlers/tests/data/pragmas/Parsermode.tid @@ -0,0 +1,36 @@ +title: Pragmas/Parsermode +description: parsermode pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +{{AlwaysInline}} + +{{AlwaysBlock}} + +{{AlwaysInline}}{{AlwaysBlock}} + ++ +title: AlwaysInline + +\parsermode inline +! Not Heading + +Text with ''bold'' ++ +title: AlwaysBlock + +\parsermode block +! Heading + +Text with ''bold'' ++ +title: ExpectedResult + +! Not Heading + +Text with bold

Heading

Text with bold

! Not Heading + +Text with bold

Heading

Text with bold

+

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/pragmas/WhitespaceAfterPragma.tid b/editions/test/tiddlers/tests/data/pragmas/WhitespaceAfterPragma.tid new file mode 100644 index 000000000..34b7b12ff --- /dev/null +++ b/editions/test/tiddlers/tests/data/pragmas/WhitespaceAfterPragma.tid @@ -0,0 +1,64 @@ +title: Pragmas/WhitespaceAfterPragma +description: parsermode pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +<$wikify name="parsetree" text={{Text}} mode="inline" output="parsetree"> +<$text text=<>/> + ++ +title: Text + +\procedure this-is-a-definition() Something + + + + +Now! + ++ +title: ExpectedResult + +

+[ + { + "type": "set", + "attributes": { + "name": { + "name": "name", + "type": "string", + "value": "this-is-a-definition" + }, + "value": { + "name": "value", + "type": "string", + "value": "Something" + } + }, + "children": [ + { + "type": "text", + "text": "Now!\n", + "start": 48, + "end": 53 + } + ], + "params": [], + "orderedAttributes": [ + { + "name": "name", + "type": "string", + "value": "this-is-a-definition" + }, + { + "name": "value", + "type": "string", + "value": "Something" + } + ], + "isProcedureDefinition": true + } +] +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/pragmas/WhitespaceNoPragma.tid b/editions/test/tiddlers/tests/data/pragmas/WhitespaceNoPragma.tid new file mode 100644 index 000000000..2a7041750 --- /dev/null +++ b/editions/test/tiddlers/tests/data/pragmas/WhitespaceNoPragma.tid @@ -0,0 +1,32 @@ +title: Pragmas/WhitespaceNoPragma +description: parsermode pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +<$wikify name="parsetree" text={{Text}} mode="inline" output="parsetree"> +<$text text=<>/> + ++ +title: Text + + + + + +Now! + ++ +title: ExpectedResult + +

+[ + { + "type": "text", + "text": "\n\n\n\nNow!\n", + "start": 0, + "end": 9 + } +] +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/EndInBody.tid b/editions/test/tiddlers/tests/data/procedures/EndInBody.tid new file mode 100644 index 000000000..3aa13fad5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/EndInBody.tid @@ -0,0 +1,16 @@ +title: Procedures/EndInBody +description: \end line starting with non-whitespace is part of procedure body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure hello() + hello \end +\end + +Out: <> ++ +title: ExpectedResult + +

Out: hello \end

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/IndentedEnd.tid b/editions/test/tiddlers/tests/data/procedures/IndentedEnd.tid new file mode 100644 index 000000000..664be3446 --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/IndentedEnd.tid @@ -0,0 +1,16 @@ +title: Procedures/IndentedEnd +description: \end line starting with whitespace ends a procedure body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure hello() + hello \end + \end + +Out: <> ++ +title: ExpectedResult + +

Out: hello \end

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/MismatchedNamedEnd.tid b/editions/test/tiddlers/tests/data/procedures/MismatchedNamedEnd.tid new file mode 100644 index 000000000..0b5385c6e --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/MismatchedNamedEnd.tid @@ -0,0 +1,16 @@ +title: Procedures/MismatchedNamedEnd +description: Mismatched named end is part of the body +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure hello() + \end goodbye +\end + +Out: <> ++ +title: ExpectedResult + +

Out: \end goodbye

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/Nested-indented.tid b/editions/test/tiddlers/tests/data/procedures/Nested-indented.tid new file mode 100644 index 000000000..75aaadb4c --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/Nested-indented.tid @@ -0,0 +1,20 @@ +title: Procedures/Nested/Indented +description: Nested Procedures that are indented +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure alpha(x) + \procedure beta(y) + <$text text=<>/> + \end beta +<$transclude $variable="beta" y={{{ [addprefix] }}}/> +\end alpha + +<> ++ +title: ExpectedResult + +

ElephantElephant

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/Nested.tid b/editions/test/tiddlers/tests/data/procedures/Nested.tid new file mode 100644 index 000000000..f63c634af --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/Nested.tid @@ -0,0 +1,20 @@ +title: Procedures/Nested +description: Nested Procedures +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure alpha(x) +\procedure beta(y) +<$text text=<>/> +\end beta +<$transclude $variable="beta" y={{{ [addprefix] }}}/> +\end alpha + +<> ++ +title: ExpectedResult + +

ElephantElephant

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/TrailingNewlines.tid b/editions/test/tiddlers/tests/data/procedures/TrailingNewlines.tid new file mode 100644 index 000000000..467235876 --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/TrailingNewlines.tid @@ -0,0 +1,22 @@ +title: Procedures/TrailingNewlines +description: Trailing newlines in procedures must not be dropped +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure inner() +Paragraph 1 + +Paragraph 2 +\end +\procedure outer() +<$macrocall $name=inner /> + +\end +<> + ++ +title: ExpectedResult + +

Paragraph 1

Paragraph 2

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd.tid b/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd.tid new file mode 100644 index 000000000..51f0b87df --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd.tid @@ -0,0 +1,18 @@ +title: Procedures/WhitespaceOnlyWithEnd +description: The /end should be detected when procedure definition contains only whitespace +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure max() +\end +Nothing +\end + +Out: <> ++ +title: ExpectedResult + +

Nothing +\end

Out:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd2.tid b/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd2.tid new file mode 100644 index 000000000..54d3ebbf6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/procedures/WhitespaceOnlyWithEnd2.tid @@ -0,0 +1,15 @@ +title: Procedures/WhitespaceOnlyWithEnd2 +description: Line with \end can start with whitespace +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure empty() + \end + +Out: <> ++ +title: ExpectedResult + +

Out:

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/this-tiddler/Simple.tid b/editions/test/tiddlers/tests/data/this-tiddler/Simple.tid new file mode 100644 index 000000000..4aad83c98 --- /dev/null +++ b/editions/test/tiddlers/tests/data/this-tiddler/Simple.tid @@ -0,0 +1,29 @@ +title: ThisTiddler/Simple +description: Simple usage of thisTiddler variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Macro +\define print-this-tiddler() +<$text text=<>/> +\end + +(<$text text=<>/>) + +(<>) + +(<>) + ++ +title: Macro + +\define imported-print-this-tiddler() +<$text text=<>/> +\end ++ +title: ExpectedResult + +

(Output)

(Output)

(Output)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid new file mode 100644 index 000000000..296aa6931 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-ActionWidget.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/ActionWidget +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='Result'> + ++ +title: Actions + +\whitespace trim + +\widget $action.mywidget(one:'Jaguar') +\whitespace trim +<$action-setfield $tiddler="Result" $field="text" $value=<>/> +\end + +<$action.mywidget one="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

Dingo

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid new file mode 100644 index 000000000..484f0c4a3 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-CodeblockOverride-TextParser.tid @@ -0,0 +1,20 @@ +title: Transclude/CustomWidget/CodeblockOverride-TextParser +description: Test that overriding codeblock widget does not impact text parser +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $codeblock(code) +<$transclude $variable="copy-to-clipboard" src=<>/> +<$genesis $type="$codeblock" $remappable="no" code=<>/> +\end + +\procedure myvariable() hello + +<$transclude $variable="myvariable" $type="text/plain" $output="text/plain"/> ++ +title: ExpectedResult + +

hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid new file mode 100644 index 000000000..3d0759013 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Fail.tid @@ -0,0 +1,26 @@ +title: Transclude/CustomWidget/Fail +description: Custom widget failed definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +\widget $non-existent-widget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-raw"> + Whale + +\end +<$non-existent-widget one="Dingo"> + Crocodile + +<$non-existent-widget one="BumbleBee"> + Squirrel + ++ +title: ExpectedResult + +

Undefined widget 'non-existent-widget'Undefined widget 'non-existent-widget'

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid new file mode 100644 index 000000000..c4730622b --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Override-Codeblock.tid @@ -0,0 +1,29 @@ +title: CustomWidget-Override-Codeblock +description: Usage of genesis widget with attributes starting with dollar signs +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definition +<$codeblock code="Kangaroo"/> +<$codeblock code={{Subject}}/> +<$let test="Tiger"> +<$codeblock code=<>/> + ++ +title: Definition + +\whitespace trim +\widget $codeblock(code) +<$genesis $type="$codeblock" $remappable="no" code={{{ [addprefix[£]addsuffix[@]] }}}/> +\end ++ +title: Subject + +Python ++ +title: ExpectedResult + +

£Kangaroo@
£Python@
£Tiger@

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid new file mode 100644 index 000000000..c57e4a9a1 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-OverrideTransclude.tid @@ -0,0 +1,33 @@ +title: Transclude/CustomWidget/OverrideTransclude +description: Custom widget definition attempting to override transclude +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerZero + +Antelope ++ +title: TiddlerOne + +\whitespace trim + +\widget $transclude(one:'Jaguar') +\whitespace trim + <$text text=<>/> + <$slot $name="body"> + Whale + +\end +<$genesis $type="$transclude" $remappable="no" $$tiddler="TiddlerZero"> + Crocodile + ++ +title: ExpectedResult + +

Antelope

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple-Indented.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple-Indented.tid new file mode 100644 index 000000000..19945e6ea --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple-Indented.tid @@ -0,0 +1,33 @@ +title: Transclude/CustomWidget/Simple/Indented +description: Custom widget definition indented +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim + + \widget $my.widget(one:'Jaguar') + \whitespace trim + <$text text=<>/> + <$slot $name="ts-raw"> + Whale + + \end +<$my.widget one="Dingo"> + Crocodile + +<$my.widget one="BumbleBee"> + Squirrel + +<$my.widget/> ++ +title: ExpectedResult + +

DingoCrocodileBumbleBeeSquirrelJaguarWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid new file mode 100644 index 000000000..ccb590d4f --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Simple.tid @@ -0,0 +1,33 @@ +title: Transclude/CustomWidget/Simple +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $my.widget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-raw"> + Whale + +\end +<$my.widget one="Dingo"> + Crocodile + +<$my.widget one="BumbleBee"> + Squirrel + +<$my.widget/> ++ +title: ExpectedResult + +

DingoCrocodileBumbleBeeSquirrelJaguarWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid new file mode 100644 index 000000000..0ada5100b --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted-Empty.tid @@ -0,0 +1,20 @@ +title: CustomWidget/Slotted/Empty +description: Custom widget with empty slotted values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $my.widget() +<$slot $name=ts-raw>the body is empty +\end + +#<$my.widget/> +#<$my.widget> +#<$my.widget>the body is not empty + ++ +title: ExpectedResult + +
  1. the body is empty
  2. the body is empty
  3. the body is not empty
\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid new file mode 100644 index 000000000..eb7d61756 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Slotted.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/Slotted +description: Custom widget definition +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\widget $my.widget(one:'Jaguar') +\whitespace trim +<$text text=<>/> +<$slot $name="ts-stuff"> + Whale + +\end +<$my.widget one="Dingo"> + <$fill $name="ts-stuff"> + Crocodile + + +<$my.widget one="BumbleBee"> + Squirrel + ++ +title: ExpectedResult + +

DingoCrocodileBumbleBeeWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid new file mode 100644 index 000000000..d0a3cc82c --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverride.tid @@ -0,0 +1,27 @@ +title: Transclude/CustomWidget/TextWidgetOverride +description: Custom widget definition redefining the text widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $text(text:'Jaguar') +\whitespace trim +<$genesis $type="$text" $remappable="no" text={{{ [addprefix[≤]addsuffix[≥]] }}}/> +\end + +<$text text="Dingo"/> + +Crocodile ++ +title: ExpectedResult + +

≤Dingo≥≤Jaguar≥

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid new file mode 100644 index 000000000..c84c5ae9a --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-TextWidgetOverrideWithSlot.tid @@ -0,0 +1,31 @@ +title: Transclude/CustomWidget/TextWidgetOverrideWithSlot +description: Custom widget definition redefining the text widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $text(text:'Jaguar') +\whitespace trim +<$genesis $type="$text" $remappable="no" text=<>/> +<$set name="$text" value=""> + <$slot $name="ts-raw"> + Whale + + +\end +<$text text="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid new file mode 100644 index 000000000..c6a834205 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-Unoverride-Codeblock.tid @@ -0,0 +1,31 @@ +title: CustomWidget-Unoverride-Codeblock +description: Usage of genesis widget with attributes starting with dollar signs, and unoverriding a core widget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\import Definition +<$let $codeblock=""> +<$codeblock code="Kangaroo"/> +<$codeblock code={{Subject}}/> +<$let test="Tiger"> +<$codeblock code=<>/> + + ++ +title: Definition + +\whitespace trim +\widget $codeblock(code) +<$genesis $type="codeblock" $remappable="no" code={{{ [addprefix[£]addsuffix[@]] }}}/> +\end ++ +title: Subject + +Python ++ +title: ExpectedResult + +

Kangaroo
Python
Tiger

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid b/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid new file mode 100644 index 000000000..e4e7dbaaf --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/CustomWidget-VariableAttribute.tid @@ -0,0 +1,29 @@ +title: Transclude/CustomWidget/VariableAttribute +description: Custom widget definition using an attribute called $variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim + +\widget $my.widget($variable:'Jaguar') +\whitespace trim +<$text text=<<$variable>>/> +<$slot $name="ts-raw"> + Whale + +\end +<$my.widget $variable="Dingo"> + Crocodile + ++ +title: ExpectedResult + +

DingoCrocodile

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid b/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid new file mode 100644 index 000000000..216a89dc8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/JavaScript-Macro.tid @@ -0,0 +1,17 @@ +title: Transclude/Macro/JavaScript +description: Transcluding a javascript macro +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<> + +<$macrocall $name="makedatauri" text="Wildebeest" type="text/plain"/> + ++ +title: ExpectedResult + +

data:text/plain,Wildebeest

data:text/plain,Wildebeest

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Macro-Missing.tid b/editions/test/tiddlers/tests/data/transclude/Macro-Missing.tid new file mode 100644 index 000000000..8a1a837e5 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Macro-Missing.tid @@ -0,0 +1,40 @@ +title: Transclude/Macro/Missing +description: Transcluding a missing or blank variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$macrocall $name="missingmacro"> +Fallback content + + +<$transclude $variable="missingmacro"> +Fallback content + + +<$macrocall $name=""> +Fallback content + + +<$transclude $variable=""> +Fallback content + + +<$let emptyVariable=""> + +<$macrocall $name="emptyVariable"> +Fallback content + + +<$transclude $variable="emptyVariable"> +Fallback content + + + + ++ +title: ExpectedResult + +

Fallback content

Fallback content

Fallback content

Fallback content

Fallback content

Fallback content

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid b/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid new file mode 100644 index 000000000..410144153 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Macro-Plain.tid @@ -0,0 +1,17 @@ +title: Transclude/Macro/Plain +description: Transcluding a macro as plain text +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let currentTab="Jeremy"> +<$macrocall $name="currentTab" $type="text/plain" $output="text/plain"/> +| +<$transclude $variable="currentTab" $type="text/plain" $output="text/plain"/> + ++ +title: ExpectedResult + +

Jeremy|Jeremy

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid b/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid new file mode 100644 index 000000000..71db5efe4 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Macro-Simple.tid @@ -0,0 +1,26 @@ +title: Transclude/Macro/Simple +description: Transcluding a macro +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\define mamacro(one:"red",two:"green") +It is $one$ and $two$ or <<__one__>> and <<__two__>>. +\end + +<$macrocall $name="mamacro"/> + +<$transclude $variable="mamacro"/> + +<$transclude $variable="mamacro" one="orange"/> + +<$transclude $variable="mamacro" 0="pink"/> + +<$transclude $variable="mamacro" one="purple" 1="pink"/> + ++ +title: ExpectedResult + +

It is red and green or red and green.

It is red and green or red and green.

It is orange and green or orange and green.

It is pink and green or pink and green.

It is purple and pink or purple and pink.

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid b/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid new file mode 100644 index 000000000..8bdc86eaa --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/MissingTarget.tid @@ -0,0 +1,48 @@ +title: Transclude/MissingTarget +description: Transcluding a missing target +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$fill $name="ts-missing"> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + + +<$transclude $tiddler='MissingTiddler' one='Ferret'> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + +<$transclude $tiddler='MissingTiddler' one='Ferret'> + <$fill $name="ts-missing"> + <$parameters one='Ferret'> + Badger + <$text text=<>/> + + + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Kangaroo'> + Piranha + <$text text=<>/> + ++ +title: ExpectedResult + +

PiranhaFerretPiranhaFerretBadgerFerretBadgerFerret

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid new file mode 100644 index 000000000..064e225c8 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Depth.tid @@ -0,0 +1,34 @@ +title: Transclude/Parameterised/Depth +description: Parameterised transclusion using the $depth attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +| +<$transclude $tiddler='TiddlerOne'/> +| +<$transclude $tiddler='TiddlerOne' one='Ferret' $$two="Osprey"/> +| +<$transclude $tiddler='TiddlerOne' $$two="Falcon"/> ++ +title: TiddlerOne + +\whitespace trim +{{TiddlerTwo}} ++ +title: TiddlerTwo + +\whitespace trim +<$parameters one='Jaguar' $$two='Piranha' $depth="2"> + <$text text=<>/>:<$text text=<<$two>>/> + +<$parameters one='Leopard' $$two='Coelacanth'> + (<$text text=<>/>|<$text text=<<$two>>/>) + ++ +title: ExpectedResult + +

Ferret:Piranha(Leopard|Coelacanth)|Jaguar:Piranha(Leopard|Coelacanth)|Ferret:Osprey(Leopard|Coelacanth)|Jaguar:Falcon(Leopard|Coelacanth)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid new file mode 100644 index 000000000..04f5bbb04 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Mode.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Mode +description: Parameterised transclusion using the $parseMode attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + +This is a block + + + +<$transclude $tiddler='TiddlerOne'> +This is inline + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $parseMode="@parseMode"> + <$text text=<<@parseMode>>/> + ++ +title: ExpectedResult + +

block

inline

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid new file mode 100644 index 000000000..9d62a7897 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Name-Values.tid @@ -0,0 +1,34 @@ +title: Transclude/Parameterised/Name/Values +description: Parameterised transclusion accessing parameters as name/value pairs +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler="TiddlerOne" 0="" 1="" 2=""/> + +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar' $$one='Lizard' two='Mole' $params="@params"> +<$list filter="[<@params>jsonindexes[]]"> +{<$text text=<>/>: <$text text={{{ [<@params>jsonget] }}}/>} + + ++ +title: TiddlerTwo + +\whitespace trim +\parameters(zero:'Mouse',$one:'Horse',two:'Owl') +(<$transclude $tiddler=<> zero=<> $$one=<<$one>> two=<>/>) ++ +title: ExpectedResult + +

{0:}{1:}{2:}

{0:Ferret}

{0:Butterfly}{1:Moth}

{0:Beetle}{1:Scorpion}{2:Snake}

({$one:Scorpion}{two:Snake}{zero:Beetle})

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid new file mode 100644 index 000000000..916e2abfb --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/ParseTreeNodes +description: Parameterised transclusion using the $parseTreeNodes attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> + +This is a block + + + +<$transclude $tiddler='TiddlerOne'> +This is inline + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $parseTreeNodes="@parseTreeNodes"> + <$text text=<<@parseTreeNodes>>/> + ++ +title: ExpectedResult + +

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid new file mode 100644 index 000000000..abf444adb --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut-Parameters.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Positional/Shortcut/Parameters +description: Positional parameterised transclusion using shortcut syntax and parameters pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +\parameters(zero:Jaguar,one:'Lizard',two:'Mole') +[{<$text text=<>/>}{<$text text=<>/>}{<$text text=<>/>}] ++ +title: TiddlerTwo + +\whitespace trim +\parameters(zero:'Mouse',one:Horse,two:'Owl') +(<$transclude $tiddler=<> zero=<> one=<> two=<>/>) ++ +title: ExpectedResult + +

[{Jaguar}{Lizard}{Mole}]

[{Ferret}{Lizard}{Mole}]

[{Butterfly}{Moth}{Mole}]

[{Beetle}{Scorpion}{Snake}]

([{Beetle}{Scorpion}{Snake}])

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid new file mode 100644 index 000000000..7792e6c66 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Shortcut.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/Positional/Shortcut +description: Positional parameterised transclusion using shortcut syntax +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +{{TiddlerOne}} +{{TiddlerOne|Ferret}} +{{TiddlerOne|Butterfly|Moth}} +{{TiddlerOne|Beetle|Scorpion|Snake}} +{{TiddlerOne||TiddlerTwo|Beetle|Scorpion|Snake}} ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar' one='Lizard' two='Mole'>[{<$text text=<>/>}{<$text text=<>/>}{<$text text=<>/>}] ++ +title: TiddlerTwo + +\whitespace trim +<$parameters zero='Mouse' one='Horse' two='Owl'> +(<$transclude $tiddler=<> zero=<> one=<> two=<>/>) + ++ +title: ExpectedResult + +

[{Jaguar}{Lizard}{Mole}]

[{Ferret}{Lizard}{Mole}]

[{Butterfly}{Moth}{Mole}]

[{Beetle}{Scorpion}{Snake}]

([{Beetle}{Scorpion}{Snake}])

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid new file mode 100644 index 000000000..ad2b7be52 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional-Variables.tid @@ -0,0 +1,30 @@ +title: Transclude/Parameterised/Positional/Variables +description: Positional parameterised transclusion of variables +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\function myfunction(alpha:"apple",beta:"banana",gamma:"grenadine") [] +\define mymacro(alpha:"apple",beta:"banana",gamma:"grenadine") $beta$ +\function f(a) [] + +(Functions: +<$text text={{{ [] }}}/> +, +<$text text=<>/> +, +<> +)(Macros: +<$text text={{{ [] }}}/> +, +<$text text=<>/> +, +<> +) + ++ +title: ExpectedResult + +

(Functions:f1,f1,f1)(Macros:banana,banana,banana)

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid new file mode 100644 index 000000000..d7eb9090e --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Positional.tid @@ -0,0 +1,26 @@ +title: Transclude/Parameterised/Positional +description: Positional parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' zero='Ferret'/> +<$transclude zero='Ferret' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne' 0='Pigeon'/> +<$transclude 0='Pigeon' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne' zero='Ferret' 0='Pigeon'/> +<$transclude zero='Ferret' 0='Pigeon' $tiddler='TiddlerOne'/> +<$transclude $tiddler='TiddlerOne'/> ++ +title: TiddlerOne + +\whitespace trim +<$parameters zero='Jaguar'> + <$text text=<>/> + ++ +title: ExpectedResult + +

FerretFerretPigeonPigeonFerretFerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid new file mode 100644 index 000000000..375964199 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-Parameters.tid @@ -0,0 +1,20 @@ +title: Transclude/Parameterised/Shortcut/Parameters +description: Simple parameterised transclusion using the parameters pragma +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +<$transclude $tiddler='TiddlerOne'/> ++ +title: TiddlerOne + +\whitespace trim +\parameters(one:'Jaguar') +<$text text=<>/> ++ +title: ExpectedResult + +

FerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-ParametersIndented.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-ParametersIndented.tid new file mode 100644 index 000000000..90e9a90aa --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut-ParametersIndented.tid @@ -0,0 +1,20 @@ +title: Transclude/Parameterised/Shortcut/ParametersIndented +description: Simple parameterised transclusion using the parameters pragma (indented) +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +<$transclude $tiddler='TiddlerOne'/> ++ +title: TiddlerOne + +\whitespace trim + \parameters(one:'Jaguar') +<$text text=<>/> ++ +title: ExpectedResult + +

FerretJaguar

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid new file mode 100644 index 000000000..0499cf2d6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Shortcut.tid @@ -0,0 +1,21 @@ +title: Transclude/Parameterised/Shortcut +description: Simple parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure test(one:'Jaguar') +{<$text text=<>/>} +\end + +<$transclude $variable='test' one='Ferret'/> +<$transclude $variable='test'/> +<> +<> + ++ +title: ExpectedResult + +

{Ferret}{Jaguar}{Rat}{Mouse}

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid new file mode 100644 index 000000000..0268f9e59 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Simple.tid @@ -0,0 +1,26 @@ +title: Transclude/Parameterised/Simple +description: Simple parameterised transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'/> +| +<$transclude $tiddler='TiddlerOne'/> +| +<$transclude $tiddler='TiddlerOne' one='Ferret' $$two="Osprey"/> +| +<$transclude $tiddler='TiddlerOne' $$two="Falcon"/> ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar' $$two='Piranha'> + <$text text=<>/>:<$text text=<<$two>>/> + ++ +title: ExpectedResult + +

Ferret:Piranha|Jaguar:Piranha|Ferret:Osprey|Jaguar:Falcon

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid new file mode 100644 index 000000000..679748375 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-SlotFillParseTreeNodes.tid @@ -0,0 +1,29 @@ +title: Transclude/Parameterised/SlotFillParseTreeNodes +description: Parameterised transclusion using the $slotFillParseTreeNodes attribute +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim + +<$transclude $tiddler='TiddlerOne' one='Ferret'> +<$fill $name="one">This is first +<$fill $name="two">But this is second + + +<$transclude $tiddler='TiddlerOne'> +<$fill $name="one">This is first +<$fill $name="two">But this is second + ++ +title: TiddlerOne + +\whitespace trim +<$parameters $slotFillParseTreeNodes="@slotFillParseTreeNodes"> + <$text text={{{ [<@slotFillParseTreeNodes>jsonindexes[]join[,]] }}}/> + ++ +title: ExpectedResult + +

one,ts-raw,two

one,ts-raw

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid new file mode 100644 index 000000000..fe399d572 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted-Missing.tid @@ -0,0 +1,24 @@ +title: Transclude/Parameterised/Slotted/Missing +description: Parameterised transclusion with slotted missing values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + ++ +title: ExpectedResult + +

FerretWhale

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid new file mode 100644 index 000000000..c795621ef --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-Slotted.tid @@ -0,0 +1,27 @@ +title: Transclude/Parameterised/Slotted +description: Parameterised transclusion with slotted values +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$transclude $tiddler='TiddlerOne' one='Ferret'> + <$fill $name="content"> + Hippopotamus + + ++ +title: TiddlerOne + +\whitespace trim +<$parameters one='Jaguar'> + <$text text=<>/> + <$slot $name="content"> + Whale + + ++ +title: ExpectedResult + +

FerretHippopotamus

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Procedures-Double-Underscore.tid b/editions/test/tiddlers/tests/data/transclude/Procedures-Double-Underscore.tid new file mode 100644 index 000000000..f22efb4f6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Procedures-Double-Underscore.tid @@ -0,0 +1,26 @@ +title: Procedures/Double/Underscore +description: Checking that procedures don't expose parameters as variables wrapped in double underscores +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure mamacro(one:"red",two:"green") +It is $one$ and $two$<<__one__>><<__two__>>. +\end + +<$macrocall $name="mamacro"/> + +<$transclude $variable="mamacro"/> + +<$transclude $variable="mamacro" one="orange"/> + +<$transclude $variable="mamacro" 0="pink"/> + +<$transclude $variable="mamacro" one="purple" 1="pink"/> + ++ +title: ExpectedResult + +

It is $one$ and $two$.

It is $one$ and $two$.

It is $one$ and $two$.

It is $one$ and $two$.

It is $one$ and $two$.

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid b/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid new file mode 100644 index 000000000..d2bded70c --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Procedures-Whitespace.tid @@ -0,0 +1,25 @@ +title: Transclude/Procedures/Whitespace +description: Procedures should inherit whitespace settings from definition site +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +\procedure testproc() +This is a sentence +\end + +\define testmacro() +This is a sentence +\end +This is a sentence +[<>] +[<>] + ++ +title: ExpectedResult + +

This is a sentence +[This is a sentence] +[This is a sentence ]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Typed.tid b/editions/test/tiddlers/tests/data/transclude/Typed.tid new file mode 100644 index 000000000..c99664b59 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Typed.tid @@ -0,0 +1,38 @@ +title: Transclude/Typed +description: Typed transclusion +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\procedure testproc() +This is ''wikitext'' +\end + +<$transclude $variable="testproc"/> +- +<$transclude $variable="testproc" $type="text/plain"/> + +<$transclude $tiddler="Data" $index="testindex"/> +- +<$transclude $tiddler="Data" $index="testindex" $type="text/plain"/> + +<$transclude $tiddler="Data" $field="custom"/> +- +<$transclude $tiddler="Data" $field="custom" $type="text/plain"/> ++ +title: Data +type: application/x-tiddler-dictionary +custom: This is ''wikitext'' + +testindex: This is ''wikitext'' ++ +title: ExpectedResult + +

This is wikitext +- +

This is ''wikitext''

This is wikitext +- +

This is ''wikitext''

This is wikitext +- +

This is ''wikitext''

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid b/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid new file mode 100644 index 000000000..c1867c2fc --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Variable-Refreshing.tid @@ -0,0 +1,27 @@ +title: Transclude/Variable/Refreshing +description: Transcluding and refreshing a function +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\function list-join(filter, sep:", ") [subfilterjoin] + +<$tiddler tiddler="TestData"> + +<> + + + ++ +title: TestData + + ++ +title: Actions + +<$action-setfield $tiddler="TestData" items={{{ [range[10]join[ ]] }}}/> ++ +title: ExpectedResult + +

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid b/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid new file mode 100644 index 000000000..4158569c6 --- /dev/null +++ b/editions/test/tiddlers/tests/data/transclude/Variable-Static.tid @@ -0,0 +1,15 @@ +title: Transclude/Variable/Static +description: Transcluding a function +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output +items: 1 2 3 4 5 6 7 8 9 10 + +\function list-join(filter, sep:", ") [subfilterjoin] + +<> ++ +title: ExpectedResult + +

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid new file mode 100644 index 000000000..da3d7080a --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/ButtonWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/ButtonWidget +description: Data Attributes for ButtonWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$button tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$button tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

my tiddler
hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid new file mode 100644 index 000000000..521fa3a13 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/CheckboxWidget-DataAttributes.tid @@ -0,0 +1,22 @@ +title: Widgets/DataAttributes/CheckboxWidget +description: Data Attributes for CheckboxWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$checkbox tag="done" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked"> Is it done? ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid new file mode 100644 index 000000000..feeb89ded --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DraggableWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/DraggableWidget +description: Data Attributes for DraggableWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$draggable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$draggable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

my tiddler
hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid new file mode 100644 index 000000000..3c7284eb1 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/DroppableWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/DroppableWidget +description: Data Attributes for DroppableWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$droppable tag="div" class="myclass" data-title="mytiddler" style.color="red" onclick="clicked"> +my tiddler + +<$droppable tag="div" class="myclass" data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}}> +hello + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

my tiddler
hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid new file mode 100644 index 000000000..e99e265bb --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/LinkWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/LinkWidget +description: Data Attributes for LinkWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$link data-id="mytiddler" style.color="red" to="Temp" onclick="clicked"> +link to Temp + +<$link tag="button" data-id={{Temp}} style.color={{{ [[Temp]get[color]] }}} to="SomeTiddler"> +some tiddler + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

link to Temp

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid new file mode 100644 index 000000000..2f6d2cb1a --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/OrderedStyleAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/DataAttributes/OrderedStyleAttributes +description: Ordered style attributes +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
+hello +
++ +title: ExpectedResult + +

hello

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid b/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid new file mode 100644 index 000000000..e2006312b --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/DataAttributes/SelectWidget-DataAttributes.tid @@ -0,0 +1,27 @@ +title: Widgets/DataAttributes/SelectWidget +description: Data Attributes for SelectWidget +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$select tiddler='New Tiddler' class="myclass" field='text' default='Choose a new text' data-title={{Temp}} style.color={{{ [[Temp]get[color]] }}} onclick="clicked"> + + + + + ++ +title: Actions + +<$action-setfield $tiddler="Temp" $field="text" $value="Title2" color="red"/> ++ +title: Temp +color: black + +Title1 ++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid b/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid new file mode 100644 index 000000000..4c2f6eb04 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/ElementWidgetEventAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/ElementWidgetEventAttributes +description: Element widget should not support event attributes starting with "on" +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
+TiddlyWiki +
++ +title: ExpectedResult + +

TiddlyWiki

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid b/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid new file mode 100644 index 000000000..a36a51323 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/ElementWidgetStyleAttributes.tid @@ -0,0 +1,15 @@ +title: Widgets/ElementWidgetStyleAttributes +description: Element widget should support style.* attributes +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +
+TiddlyWiki +
++ +title: ExpectedResult + +

TiddlyWiki

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid b/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid new file mode 100644 index 000000000..b81fc7d75 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/LetWidgetSelfReferences.tid @@ -0,0 +1,15 @@ +title: Widgets/LetWidgetSelfReferences +description: Test let widget self references +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let default={{{ [[default]is[variable]then[aa]else[bb]] }}} > +<> + ++ +title: ExpectedResult + +

bb

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid b/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid new file mode 100644 index 000000000..e6163d915 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/LetWidgetUndefinedVariable.tid @@ -0,0 +1,15 @@ +title: Widgets/LetWidgetUndefinedVariable +description: Test let widget undefined variable +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$let test1=<> test2={{{ [] }}}> +<> + ++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid new file mode 100644 index 000000000..9d5538573 --- /dev/null +++ b/editions/test/tiddlers/tests/data/widgets/SubstitutedAttributes.tid @@ -0,0 +1,21 @@ +title: Widgets/SubstitutedAttributes +description: Attributes specified as string that should have substitution performed. +type: text/vnd.tiddlywiki-multiple +tags: [[$:/tags/wiki-test-spec]] + +title: Output + +\whitespace trim +<$set name="var with spaces" value="spaces"> +<$let project="TiddlyWiki" disabled="true" var-with-dashes="dashes"> +
+
+ + + ++ +title: ExpectedResult + +

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-checkbox-widget.js b/editions/test/tiddlers/tests/test-checkbox-widget.js index a6572afd6..b0921e286 100644 --- a/editions/test/tiddlers/tests/test-checkbox-widget.js +++ b/editions/test/tiddlers/tests/test-checkbox-widget.js @@ -56,7 +56,7 @@ Tests the checkbox widget thoroughly. * Test data for checkbox widget tests */ - const fieldModeTests = [ + var fieldModeTests = [ { testName: "field mode checked", tiddlers: [{title: "TiddlerOne", text: "Jolly Old World", expand: "yes"}], @@ -95,16 +95,16 @@ Tests the checkbox widget thoroughly. }, ]; - const indexModeTests = fieldModeTests.map(data => { - const newData = {...data}; - const newName = data.testName.replace('field mode', 'index mode'); - const newTiddlers = data.tiddlers.map(tiddler => { + var indexModeTests = fieldModeTests.map(data => { + var newData = {...data}; + var newName = data.testName.replace('field mode', 'index mode'); + var newTiddlers = data.tiddlers.map(tiddler => { return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nexpand: ${tiddler.expand}\ntwo: b`} }); - const newWidgetText = data.widgetText.replace("field='expand'", "index='expand'"); - const newChange = {}; - for (const key of Object.keys(data.expectedChange)) { - const oldChange = data.expectedChange[key]; + var newWidgetText = data.widgetText.replace("field='expand'", "index='expand'"); + var newChange = {}; + for (var key of Object.keys(data.expectedChange)) { + var oldChange = data.expectedChange[key]; if (oldChange.expand) { newChange[key] = { text: `one: a\nexpand: ${oldChange.expand}\ntwo: b` } } else { @@ -119,7 +119,26 @@ Tests the checkbox widget thoroughly. return newData; }); - const listModeTests = [ + var listModeTestsForDateFields = [ + { + testName: "list mode created date field", + tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}], + widgetText: "<$checkbox tiddler='Colors' listField='created' checked='green' />", + startsOutChecked: false, + finalValue: false, + expectedChange: { "Colors": { created: new Date("2013-04-15T22:22:00Z")}} // created field should *not* be touched by a listField checkbox + }, + { + testName: "list mode modified date field", + tiddlers: [{title: "Colors", created: "201304152222", modified: "202301022222"}], + widgetText: "<$checkbox tiddler='Colors' listField='modified' checked='green' />", + startsOutChecked: false, + finalValue: false, + expectedChange: { "Colors": { modified: new Date("2023-01-02T22:22:00Z")}} // modified field should *not* be touched by a listField checkbox + }, + ] + + var listModeTests = [ { testName: "list mode add", tiddlers: [{title: "Colors", colors: "orange yellow"}], @@ -235,11 +254,11 @@ Tests the checkbox widget thoroughly. ]; // https://github.com/Jermolene/TiddlyWiki5/issues/6871 - const listModeTestsWithListField = ( + var listModeTestsWithListField = ( listModeTests .filter(data => data.widgetText.includes("listField='colors'")) .map(data => { - const newData = { + var newData = { ...data, tiddlers: data.tiddlers.map(tiddler => ({...tiddler, list: tiddler.colors, colors: undefined})), widgetText: data.widgetText.replace("listField='colors'", "listField='list'"), @@ -250,11 +269,11 @@ Tests the checkbox widget thoroughly. return newData; }) ); - const listModeTestsWithTagsField = ( + var listModeTestsWithTagsField = ( listModeTests .filter(data => data.widgetText.includes("listField='colors'")) .map(data => { - const newData = { + var newData = { ...data, tiddlers: data.tiddlers.map(tiddler => ({...tiddler, tags: tiddler.colors, colors: undefined})), widgetText: data.widgetText.replace("listField='colors'", "listField='tags'"), @@ -266,20 +285,20 @@ Tests the checkbox widget thoroughly. }) ); - const indexListModeTests = listModeTests.map(data => { - const newData = {...data}; - const newName = data.testName.replace('list mode', 'index list mode'); - const newTiddlers = data.tiddlers.map(tiddler => { + var indexListModeTests = listModeTests.map(data => { + var newData = {...data}; + var newName = data.testName.replace('list mode', 'index list mode'); + var newTiddlers = data.tiddlers.map(tiddler => { if (tiddler.hasOwnProperty('colors')) { return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\ncolors: ${tiddler.colors}\ntwo: b`} } else if (tiddler.hasOwnProperty('someField')) { return {title: tiddler.title, type: "application/x-tiddler-dictionary", text: `one: a\nsomeField: ${tiddler.someField}\ntwo: b`} } }); - const newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'"); - const newChange = {}; - for (const key of Object.keys(data.expectedChange)) { - const oldChange = data.expectedChange[key]; + var newWidgetText = data.widgetText.replace("listField='colors'", "listIndex='colors'").replace(/\$field/g, '$index').replace("listField='someField'", "listIndex='someField'"); + var newChange = {}; + for (var key of Object.keys(data.expectedChange)) { + var oldChange = data.expectedChange[key]; if (oldChange.colors) { newChange[key] = { text: `one: a\ncolors: ${oldChange.colors}\ntwo: b` } } else if (oldChange.someField !== undefined) { @@ -296,7 +315,7 @@ Tests the checkbox widget thoroughly. return newData; }); - const filterModeTests = [ + var filterModeTests = [ { testName: "filter mode false -> true", tiddlers: [{title: "Colors", colors: "red orange yellow"}], @@ -482,9 +501,10 @@ Tests the checkbox widget thoroughly. }, ]; - const checkboxTestData = fieldModeTests.concat( + var checkboxTestData = fieldModeTests.concat( indexModeTests, listModeTests, + listModeTestsForDateFields, listModeTestsWithListField, listModeTestsWithTagsField, indexListModeTests, @@ -494,7 +514,7 @@ Tests the checkbox widget thoroughly. /* * Checkbox widget tests using the test data above */ - for (const data of checkboxTestData) { + for (var data of checkboxTestData) { it('checkbox widget test: ' + data.testName, function() { // Setup @@ -505,7 +525,7 @@ Tests the checkbox widget thoroughly. // Check initial state - const widget = findNodeOfType('checkbox', widgetNode); + var widget = findNodeOfType('checkbox', widgetNode); // Verify that the widget is or is not checked as expected expect(widget.getValue()).toBe(data.startsOutChecked); @@ -519,16 +539,16 @@ Tests the checkbox widget thoroughly. widget.handleChangeEvent(null); // Check state again: in most tests, checkbox should be inverse of what it was - const finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked; + var finalValue = data.hasOwnProperty('finalValue') ? data.finalValue : !data.startsOutChecked; expect(widget.getValue()).toBe(finalValue); // Check that tiddler(s) has/have gone through expected change(s) - for (const key of Object.keys(data.expectedChange)) { - const tiddler = wiki.getTiddler(key); - const change = data.expectedChange[key]; - for (const fieldName of Object.keys(change)) { - const expectedValue = change[fieldName]; - const fieldValue = tiddler.fields[fieldName]; + for (var key of Object.keys(data.expectedChange)) { + var tiddler = wiki.getTiddler(key); + var change = data.expectedChange[key]; + for (var fieldName of Object.keys(change)) { + var expectedValue = change[fieldName]; + var fieldValue = tiddler.fields[fieldName]; expect(fieldValue).toEqual(expectedValue); } } diff --git a/editions/test/tiddlers/tests/test-deserialize-operator.js b/editions/test/tiddlers/tests/test-deserialize-operator.js new file mode 100644 index 000000000..c629de3ae --- /dev/null +++ b/editions/test/tiddlers/tests/test-deserialize-operator.js @@ -0,0 +1,44 @@ +/*\ +title: test-deserialize-operator.js +type: application/javascript +tags: [[$:/tags/test-spec]] + +Tests deserialize[] filter operator with various core deserializers + +\*/ +(function(){ + + /* jslint node: true, browser: true */ + /* eslint-env node, browser, jasmine */ + /* eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/ + /* global $tw, require */ + "use strict"; + + + describe("deserialize operator tests", function() { + + it("should support the deserialize[] operator", function() { + //Unknown deserializer as operand + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[unknown/deserializer]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/UnknownDeserializer")]); + + //Missing operand + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[]]")).toEqual([$tw.language.getString("Error/DeserializeOperator/MissingOperand")]); + + //Deserialize TiddlyWiki file + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 4}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"}]']); + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[text/html]]")).toEqual(['[{"type":"text/vnd.tiddlywiki","text":"Abacus","title":"Hello \\"There\\""},{"title":"Hello \\"There\\"","text":"Calculator"},{"title":"Hello \\"There\\"","text":"Protractor"}]']); + + // Deserialize JSON payload containing tiddlers + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]]")).toEqual( [ `[{"created":"20230601125557184","text":"Before you start storing important information in ~TiddlyWiki it is vital to make sure that you can reliably save changes. See https://tiddlywiki.com/#GettingStarted for details\\n\\n","title":"GettingStarted","modified":"20230601125601619"},{"created":"20230601125507054","text":"Welcome to \\"TiddlyWiki\\".\\n\\nThis is a test tiddler.","tags":"","title":"Hello There \\"Welcome\\"","modified":"20230601125551144"},{"title":"TiddlyWiki","created":"20130822170700000","modified":"20170127221451610","tags":"Concepts","type":"text/vnd.tiddlywiki","text":"~TiddlyWiki is a rich, interactive tool for manipulating complex data with structure that doesn't easily fit into conventional tools like spreadsheets or wordprocessors.\\n\\n~TiddlyWiki is designed to fit around your brain, helping you deal with the things that won't fit."}]` ]); + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 6}deserialize[application/json]jsonindexes[]] :map[{dezerializer test data case 6}jsonget,[title]]")).toEqual([ 'GettingStarted', 'Hello There "Welcome"', 'TiddlyWiki' ]); + + //Deserialize TiddlyWiki file with an mismatched deserializer + expect($tw.wiki.filterTiddlers("[{dezerializer test data case 5}deserialize[application/json]]")).toEqual([jasmine.stringMatching('JSON error')]); + }); + }); + +})(); + + + + \ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 4699e96c6..727f64ca4 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -99,14 +99,14 @@ Tests the filtering mechanism. }, "TiddlerSix": { title: "TiddlerSix", - text: "Missing inaction from TiddlerOne", + text: "Missing inaction from [[TiddlerOne]]", filter: "[[one]] [[a a]] [subfilter{hasList!!list}]", tags: [] }, "TiddlerSeventh": { title: "TiddlerSeventh", text: "", - list: "TiddlerOne [[Tiddler Three]] [[a fourth tiddler]] MissingTiddler", + list: "[[TiddlerOne]] [[Tiddler Three]] [[a fourth tiddler]] [[MissingTiddler]]", tags: ["one"] }, "Tiddler8": { @@ -144,7 +144,7 @@ Tests the filtering mechanism. modified: "201304152211" },{ title: "Tiddler Three", - text: "The speed of sound in light\n\nThere is no TiddlerZero but TiddlerSix", + text: "The speed of sound in light\n\nThere is no [[TiddlerZero]] but [[TiddlerSix]]", tags: ["one","two"], cost: "56", value: "80", @@ -252,9 +252,9 @@ Tests the filtering mechanism. }); it("should handle the lookup operator", function() { - expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,,Tidd"); - expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd"); - expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd"); + expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],,Tidd"); + expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd"); + expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler],[text]]").join(",")).toBe("Missing inaction from [[TiddlerOne]],8,Tidd"); expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler],[tags]]").join(",")).toBe(",one,one"); }); @@ -365,6 +365,7 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[sort[title]first[8]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three"); expect(wiki.filterTiddlers("[sort[title]first[x]]").join(",")).toBe("$:/ShadowPlugin"); expect(wiki.filterTiddlers("[sort[title]last[]]").join(",")).toBe("TiddlerOne"); + expect(wiki.filterTiddlers("[sort[title]last[0]]").join(",")).toBe(""); expect(wiki.filterTiddlers("[sort[title]last[2]]").join(",")).toBe("Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[sort[title]last[8]]").join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[sort[title]last[x]]").join(",")).toBe("TiddlerOne"); @@ -397,8 +398,8 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[all[shadows]tag[two]]").join(",")).toBe("$:/TiddlerFive"); expect(wiki.filterTiddlers("[all[shadows+tiddlers]tag[two]]").join(",")).toBe("$:/TiddlerFive,$:/TiddlerTwo,Tiddler Three"); expect(wiki.filterTiddlers("[all[tiddlers+shadows]tag[two]]").join(",")).toBe("$:/TiddlerTwo,Tiddler Three,$:/TiddlerFive"); - expect(wiki.filterTiddlers("[all[shadows+tiddlers]]").join(",")).toBe("$:/TiddlerFive,TiddlerSix,TiddlerSeventh,Tiddler8,$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne"); - expect(wiki.filterTiddlers("[all[tiddlers+shadows]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne,$:/TiddlerFive,TiddlerSix,TiddlerSeventh,Tiddler8"); + expect(wiki.filterTiddlers("[all[shadows+tiddlers]]").join(",")).toBe("$:/TiddlerFive,Tiddler8,TiddlerSeventh,TiddlerSix,$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne"); + expect(wiki.filterTiddlers("[all[tiddlers+shadows]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne,$:/TiddlerFive,Tiddler8,TiddlerSeventh,TiddlerSix"); expect(wiki.filterTiddlers("[all[tiddlers]tag[two]]").join(",")).toBe("$:/TiddlerTwo,Tiddler Three"); expect(wiki.filterTiddlers("[all[orphans+tiddlers+tags]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,Tiddler Three,TiddlerOne,two,one"); }); @@ -420,10 +421,10 @@ Tests the filtering mechanism. it("should handle the tagging operator", function() { expect(wiki.filterTiddlers("[[one]tagging[]sort[title]]").join(",")).toBe("Tiddler Three,Tiddler8,TiddlerOne,TiddlerSeventh"); - expect(wiki.filterTiddlers("[[one]tagging[]]").join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8"); + expect(wiki.filterTiddlers("[[one]tagging[]]").join(",")).toBe("Tiddler Three,TiddlerOne,Tiddler8,TiddlerSeventh"); expect(wiki.filterTiddlers("[[two]tagging[]sort[title]]").join(",")).toBe("$:/TiddlerFive,$:/TiddlerTwo,Tiddler Three"); - var fakeWidget = {getVariable: function() {return "one";}}; - expect(wiki.filterTiddlers("[all[current]tagging[]]",fakeWidget).join(",")).toBe("Tiddler Three,TiddlerOne,TiddlerSeventh,Tiddler8"); + var fakeWidget = {wiki: wiki, getVariable: function(name) {return name === "currentTiddler" ? "one": undefined;}}; + expect(wiki.filterTiddlers("[all[current]tagging[]]",fakeWidget).join(",")).toBe("Tiddler Three,TiddlerOne,Tiddler8,TiddlerSeventh"); }); it("should handle the untagged operator", function() { @@ -625,7 +626,7 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[{!!title}]").join(",")).toBe(""); expect(wiki.filterTiddlers("[prefix{Tiddler8}] +[sort[title]]").join(",")).toBe("Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[modifier{Tiddler8!!test-field}] +[sort[title]]").join(",")).toBe("TiddlerOne"); - var fakeWidget = {wiki: wiki, getVariable: function() {return "Tiddler Three";}}; + var fakeWidget = {wiki: wiki, getVariable: function(name) {return name === "currentTiddler" ? "Tiddler Three": undefined;}}; expect(wiki.filterTiddlers("[modifier{!!modifier}] +[sort[title]]",fakeWidget).join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,one,Tiddler Three"); }); @@ -983,16 +984,22 @@ Tests the filtering mechanism. rootWidget.setVariable("sort2","[get[text]else[]length[]]"); rootWidget.setVariable("sort3","[{!!value}divide{!!cost}]"); rootWidget.setVariable("sort4","[{!!title}]"); + rootWidget.setVariable("undefined-variable","[]"); + rootWidget.setVariable("echo","$text$",[{name:"text"}],true); + rootWidget.setVariable("sort4-macro-param","[subfilter]"); expect(wiki.filterTiddlers("[sortsub:number]",anchorWidget).join(",")).toBe("one,hasList,has filter,TiddlerOne,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test"); expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne,hasList,one"); expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("has filter,TiddlerOne,$:/TiddlerTwo,Tiddler Three,$:/ShadowPlugin,a fourth tiddler,filter regexp test,one,hasList"); expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("hasList,one,filter regexp test,a fourth tiddler,$:/ShadowPlugin,$:/TiddlerTwo,Tiddler Three,has filter,TiddlerOne"); - expect(wiki.filterTiddlers("[sortsub:number]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test,$:/ShadowPlugin"); - expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,has filter,hasList,TiddlerOne,one"); - expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,Tiddler Three,$:/TiddlerTwo,filter regexp test"); - expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("filter regexp test,$:/TiddlerTwo,Tiddler Three,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one"); + expect(wiki.filterTiddlers("[sortsub:number]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test,$:/ShadowPlugin"); + expect(wiki.filterTiddlers("[!sortsub:number]",anchorWidget).join(",")).toBe("$:/ShadowPlugin,filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,has filter,hasList,TiddlerOne,one"); + expect(wiki.filterTiddlers("[sortsub:string]",anchorWidget).join(",")).toBe("one,TiddlerOne,hasList,has filter,$:/ShadowPlugin,a fourth tiddler,$:/TiddlerTwo,Tiddler Three,filter regexp test"); + expect(wiki.filterTiddlers("[!sortsub:string]",anchorWidget).join(",")).toBe("filter regexp test,Tiddler Three,$:/TiddlerTwo,a fourth tiddler,$:/ShadowPlugin,has filter,hasList,TiddlerOne,one"); expect(wiki.filterTiddlers("[[TiddlerOne]] [[$:/TiddlerTwo]] [[Tiddler Three]] [[a fourth tiddler]] +[!sortsub:number]",anchorWidget).join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler"); expect(wiki.filterTiddlers("a1 a10 a2 a3 b10 b3 b1 c9 c11 c1 +[sortsub:alphanumeric]",anchorWidget).join(",")).toBe("a1,a2,a3,a10,b1,b3,b10,c1,c9,c11"); + // #7155. The order of the output is the same as the input when an undefined variable is used in the subfitler + expect(wiki.filterTiddlers("a2 a10 a1 +[sortsub:alphanumeric]",anchorWidget).join(",")).toBe("a2,a10,a1"); + expect(wiki.filterTiddlers("a1 a10 a2 a3 b10 b3 b1 c9 c11 c1 +[sortsub:alphanumeric]",anchorWidget).join(",")).toBe("a1,a2,a3,a10,b1,b3,b10,c1,c9,c11"); }); it("should handle the toggle operator", function() { @@ -1054,10 +1061,17 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[[Hello There]] [[GettingStarted]] +[format:titlelist[]]").join(" ")).toBe("[[Hello There]] GettingStarted"); expect(wiki.filterTiddlers("[title[Hello There]] +[format:titlelist[]]").join(" ")).toBe("[[Hello There]]"); expect(wiki.filterTiddlers("[title[HelloThere]] +[format:titlelist[]]").join(" ")).toBe("HelloThere"); + expect(wiki.filterTiddlers("0 +[format:timestamp[]]").join(",")).toBe("19700101000000000"); + expect(wiki.filterTiddlers("1603188514443 +[format:timestamp[]]").join(",")).toBe("20201020100834443"); + expect(wiki.filterTiddlers("void +[format:timestamp[]]").join(",")).toBe(""); }); it("should handle the deserializers operator", function() { - expect(wiki.filterTiddlers("[deserializers[]]").join(",")).toBe("application/javascript,application/json,application/x-tiddler,application/x-tiddler-html-div,application/x-tiddlers,text/css,text/html,text/plain"); + var expectedDeserializers = ["application/javascript","application/json","application/x-tiddler","application/x-tiddler-html-div","application/x-tiddlers","text/css","text/html","text/plain"]; + if($tw.browser) { + expectedDeserializers.unshift("(DOM)"); + } + expect(wiki.filterTiddlers("[deserializers[]]").join(",")).toBe(expectedDeserializers.join(",")); }); it("should handle the charcode operator", function() { @@ -1065,6 +1079,20 @@ Tests the filtering mechanism. expect(wiki.filterTiddlers("[charcode[9],[10]]").join(" ")).toBe(String.fromCharCode(9) + String.fromCharCode(10)); expect(wiki.filterTiddlers("[charcode[]]").join(" ")).toBe(""); }); + + it("should handle the levenshtein operator", function() { + expect(wiki.filterTiddlers("[[apple]levenshtein[apple]]").join(" ")).toBe("0"); + expect(wiki.filterTiddlers("[[apple]levenshtein[banana]]").join(" ")).toBe("9"); + expect(wiki.filterTiddlers("[[representation]levenshtein[misreprehensionisation]]").join(" ")).toBe("10"); + expect(wiki.filterTiddlers("[[the cat sat on the mat]levenshtein[the hat saw in every category]]").join(" ")).toBe("13"); + }); + + it("should handle the makepatches operator", function() { + expect(wiki.filterTiddlers("[[apple]makepatches[apple]]").join(" ")).toBe(""); + expect(wiki.filterTiddlers("[[apple]makepatches[banana]]").join(" ")).toBe("@@ -1,5 +1,6 @@\n-apple\n+banana\n"); + expect(wiki.filterTiddlers("[[representation]makepatches[misreprehensionisation]]").join(" ")).toBe("@@ -1,13 +1,21 @@\n+mis\n repre\n-sent\n+hensionis\n atio\n"); + expect(wiki.filterTiddlers("[[the cat sat on the mat]makepatches[the hat saw in every category]]").join(" ")).toBe("@@ -1,22 +1,29 @@\n the \n-c\n+h\n at sa\n-t on the mat\n+w in every category\n"); + }); it("should parse filter variable parameters", function(){ expect($tw.utils.parseFilterVariable("currentTiddler")).toEqual( @@ -1101,6 +1129,10 @@ Tests the filtering mechanism. { name: '', params: [] } ); }); + + it("should handle the encodeuricomponent and decodeuricomponent operators", function() { + expect(wiki.filterTiddlers("[[<>:\"/\\|?*]encodeuricomponent[]]").join(",")).toBe("%3C%3E%3A%22%2F%5C%7C%3F%2A"); + }); } diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index cdc8dee47..d2266ca5e 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -161,6 +161,16 @@ describe("HTML tag new parser tests", function() { expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual( { type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 } ); + expect($tw.utils.parseAttribute("p=`blah` ",1)).toEqual(null); + expect($tw.utils.parseAttribute("p=`blah` ",0)).toEqual( + { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 8 } + ); + expect($tw.utils.parseAttribute("p=```blah``` ",0)).toEqual( + { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 12 } + ); + expect($tw.utils.parseAttribute("p=`Hello \"There\"`",0)).toEqual( + { start: 0, name: 'p', type: 'substituted', rawValue: 'Hello "There"', end: 17 } + ); }); it("should parse HTML tags", function() { diff --git a/editions/test/tiddlers/tests/test-json-filters.js b/editions/test/tiddlers/tests/test-json-filters.js index c892c2419..bfb8a4504 100644 --- a/editions/test/tiddlers/tests/test-json-filters.js +++ b/editions/test/tiddlers/tests/test-json-filters.js @@ -23,7 +23,7 @@ describe("json filter tests", function() { type: "application/json" },{ title: "Second", - text: '["une","deux","trois"]', + text: '["une","deux","trois",["quatre","cinq"]]', type: "application/json" },{ title: "Third", @@ -38,23 +38,52 @@ describe("json filter tests", function() { it("should support the jsonget operator", function() { expect(wiki.filterTiddlers("[{Third}jsonget[]]")).toEqual(["This is not JSON"]); - expect(wiki.filterTiddlers("[{First}jsonget[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); + expect(wiki.filterTiddlers("[{Second}jsonget[]]")).toEqual(["une","deux","trois","quatre","cinq"]); + expect(wiki.filterTiddlers("[{First}jsonget[]]")).toEqual(["one","","1.618","four","five","six","true","false","null"]); expect(wiki.filterTiddlers("[{First}jsonget[a]]")).toEqual(["one"]); + expect(wiki.filterTiddlers("[{First}jsonget[a],[fixed]]")).toEqual([]); expect(wiki.filterTiddlers("[{First}jsonget[b]]")).toEqual([""]); + expect(wiki.filterTiddlers("[{First}jsonget[c]]")).toEqual(["1.618"]); expect(wiki.filterTiddlers("[{First}jsonget[missing-property]]")).toEqual([]); - expect(wiki.filterTiddlers("[{First}jsonget[d]]")).toEqual(['{"e":"four","f":["five","six",true,false,null]}']); - expect(wiki.filterTiddlers("[{First}jsonget[d]jsonget[f]]")).toEqual(['["five","six",true,false,null]']); + expect(wiki.filterTiddlers("[{First}jsonget[d]]")).toEqual(["four","five","six","true","false","null"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[e]]")).toEqual(["four"]); - expect(wiki.filterTiddlers("[{First}jsonget[d],[f]]")).toEqual(['["five","six",true,false,null]']); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f]]")).toEqual(["five","six","true","false","null"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[0]]")).toEqual(["five"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[1]]")).toEqual(["six"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[2]]")).toEqual(["true"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[3]]")).toEqual(["false"]); expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[4]]")).toEqual(["null"]); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[-5]]")).toEqual(["five"]); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[-4]]")).toEqual(["six"]); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[-3]]")).toEqual(["true"]); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[-2]]")).toEqual(["false"]); + expect(wiki.filterTiddlers("[{First}jsonget[d],[f],[-1]]")).toEqual(["null"]); + }); + + it("should support the jsonextract operator", function() { + expect(wiki.filterTiddlers("[{Third}jsonextract[]]")).toEqual(['"This is not JSON"']); + expect(wiki.filterTiddlers("[{First}jsonextract[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); + expect(wiki.filterTiddlers("[{First}jsonextract[a]]")).toEqual(['"one"']); + expect(wiki.filterTiddlers("[{First}jsonextract[b]]")).toEqual(['""']); + expect(wiki.filterTiddlers("[{First}jsonextract[missing-property]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonextract[d]]")).toEqual(['{"e":"four","f":["five","six",true,false,null]}']); + expect(wiki.filterTiddlers("[{First}jsonextract[d]jsonextract[f]]")).toEqual(['["five","six",true,false,null]']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[e]]")).toEqual(['"four"']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f]]")).toEqual(['["five","six",true,false,null]']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[0]]")).toEqual(['"five"']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[1]]")).toEqual(['"six"']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[2]]")).toEqual(["true"]); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[3]]")).toEqual(["false"]); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[4]]")).toEqual(["null"]); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[-5]]")).toEqual(['"five"']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[-4]]")).toEqual(['"six"']); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[-3]]")).toEqual(["true"]); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[-2]]")).toEqual(["false"]); + expect(wiki.filterTiddlers("[{First}jsonextract[d],[f],[-1]]")).toEqual(["null"]); }); it("should support the jsonindexes operator", function() { - expect(wiki.filterTiddlers("[{Second}jsonindexes[]]")).toEqual(["0","1","2"]); + expect(wiki.filterTiddlers("[{Second}jsonindexes[]]")).toEqual(["0","1","2","3"]); expect(wiki.filterTiddlers("[{First}jsonindexes[]]")).toEqual(["a","b","c","d"]); expect(wiki.filterTiddlers("[{First}jsonindexes[a]]")).toEqual([]); expect(wiki.filterTiddlers("[{First}jsonindexes[b]]")).toEqual([]); @@ -66,6 +95,11 @@ describe("json filter tests", function() { expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[2]]")).toEqual([]); expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[3]]")).toEqual([]); expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[4]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[-5]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[-4]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[-3]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[-2]]")).toEqual([]); + expect(wiki.filterTiddlers("[{First}jsonindexes[d],[f],[-1]]")).toEqual([]); }); it("should support the jsontype operator", function() { @@ -82,6 +116,31 @@ describe("json filter tests", function() { expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[2]]")).toEqual(["boolean"]); expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[3]]")).toEqual(["boolean"]); expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[4]]")).toEqual(["null"]); + expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[-5]]")).toEqual(["string"]); + expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[-4]]")).toEqual(["string"]); + expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[-3]]")).toEqual(["boolean"]); + expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[-2]]")).toEqual(["boolean"]); + expect(wiki.filterTiddlers("[{First}jsontype[d],[f],[-1]]")).toEqual(["null"]); + }); + + it("should support the jsonset operator", function() { + expect(wiki.filterTiddlers("[jsonset[a],[aa]]")).toEqual(['"First"','"Second"','"Third"']); + expect(wiki.filterTiddlers("[{First}jsonset[]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); + expect(wiki.filterTiddlers("[{First}jsonset[],[Antelope]]")).toEqual(['"Antelope"']); + expect(wiki.filterTiddlers("[{First}jsonset:number[],[not a number]]")).toEqual(['0']); + expect(wiki.filterTiddlers("[{First}jsonset[id],[Antelope]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":"Antelope"}']); + expect(wiki.filterTiddlers("[{First}jsonset:notatype[id],[Antelope]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":"Antelope"}']); + expect(wiki.filterTiddlers("[{First}jsonset:boolean[id],[false]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":false}']); + expect(wiki.filterTiddlers("[{First}jsonset:boolean[id],[Antelope]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); + expect(wiki.filterTiddlers("[{First}jsonset:number[id],[42]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":42}']); + expect(wiki.filterTiddlers("[{First}jsonset:null[id]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":null}']); + expect(wiki.filterTiddlers("[{First}jsonset:array[d],[f],[5]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null,[]]}}']); + expect(wiki.filterTiddlers("[{First}jsonset:object[d],[f],[5]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null,{}]}}']); + expect(wiki.filterTiddlers("[{First}jsonset:number[d],[f],[-1],[42]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,42]}}']); + expect(wiki.filterTiddlers("[{First}jsonset[missing],[id],[Antelope]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); + expect(wiki.filterTiddlers("[{First}jsonset:json[\"Antelope\"]]")).toEqual(['"Antelope"']); + expect(wiki.filterTiddlers("[{First}jsonset:json[id],[{\"a\":313}]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]},"id":{"a":313}}']); + expect(wiki.filterTiddlers("[{First}jsonset:json[notjson]]")).toEqual(['{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}']); }); it("should support the format:json operator", function() { diff --git a/editions/test/tiddlers/tests/test-linked-list.js b/editions/test/tiddlers/tests/test-linked-list.js index cf16fb91c..de477257d 100644 --- a/editions/test/tiddlers/tests/test-linked-list.js +++ b/editions/test/tiddlers/tests/test-linked-list.js @@ -59,10 +59,35 @@ describe("LinkedList class tests", function() { return pair; }; + // This returns an array in reverse using a LinkList's prev member. Thus + // testing that prev is not corrupt. It doesn't exist in the LinkList module + // itself to avoid full support for it. Maybe that will change later. + function toReverseArray(list) { + var visits = Object.create(null), + value = list.prev.get(null), + array = []; + while(value !== null) { + array.push(value); + var prev = list.prev.get(value); + if(Array.isArray(prev)) { + var i = (visits[value] || prev.length) - 1; + visits[value] = i; + value = prev[i]; + } else { + value = prev; + } + } + return array; + }; + // compares an array and a linked list to make sure they match up function compare(pair) { - expect(pair.list.toArray()).toEqual(pair.array); + var forward = pair.list.toArray(); + expect(forward).toEqual(pair.array); expect(pair.list.length).toBe(pair.array.length); + // Now we reverse the linked list and test it back to front, thus + // confirming that the list.prev isn't corrupt. + expect(toReverseArray(pair.list)).toEqual(forward.reverse()); return pair; }; @@ -115,7 +140,7 @@ describe("LinkedList class tests", function() { // for list.last to be anything other than a string, but I // can't figure out how to make that corruption manifest a problem. // So I dig into its private members. Bleh... - expect(typeof pair.list.last).toBe("string"); + expect(typeof pair.list.prev.get(null)).toBe("string"); }); it("can pushTop value linked to by a repeat item", function() { @@ -137,6 +162,21 @@ describe("LinkedList class tests", function() { compare(pushTop(newPair(["C", "X", "A", "A"]), "X")); // CAAX }); + it("can remove all instances of a multi-instance value #7059", function() { + // Remove duplicate items when one or more items between the duplicates + // are not removed and the first of those duplicates is not the first item. + // These tests used to fail prior to the fix to #7059 + compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "C", "A", "A"])); // B + compare(remove(newPair(["A", "A", "C", "B", "A"]), ["C", "A", "A", "A"])); // B + compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "A", "A"])); // CB + compare(remove(newPair(["A", "A", "C", "B", "A"]), ["A", "A", "A", "C"])); // B + compare(remove(newPair(["A", "A", "B", "A"]), ["A", "A", "A"])); // B + compare(remove(newPair(["A", "A", "B", "A"]), ["A", "A", "A", "B"])); // + compare(remove(newPair(["C", "A", "B", "A"]), ["C", "A", "A"])); // B + compare(remove(newPair(["C", "A", "B", "A", "C"]), ["C", "A", "A", "C"])); // B + compare(remove(newPair(["B", "A", "B", "A"]), ["B", "A", "A"])); // B + }); + it("can handle particularly nasty pushTop pitfall", function() { var pair = newPair(["A", "B", "A", "C"]); pushTop(pair, "A"); // BACA diff --git a/editions/test/tiddlers/tests/test-parsetextreference.js b/editions/test/tiddlers/tests/test-parsetextreference.js index 376ad9ec4..59f885232 100644 --- a/editions/test/tiddlers/tests/test-parsetextreference.js +++ b/editions/test/tiddlers/tests/test-parsetextreference.js @@ -124,7 +124,7 @@ describe("Wiki.parseTextReference tests", function() { // Non-existent subtiddler of a plugin expect(parseAndGetSource("$:/ShadowPlugin","text",null,"MyMissingTiddler")).toEqual(null); // Plain text tiddler - expect(parseAndGetSource("TiddlerNine")).toEqual(undefined); + expect(parseAndGetSource("TiddlerNine")).toEqual("this is plain text"); }); }); diff --git a/editions/test/tiddlers/tests/test-popup.js b/editions/test/tiddlers/tests/test-popup.js new file mode 100644 index 000000000..455da2b9b --- /dev/null +++ b/editions/test/tiddlers/tests/test-popup.js @@ -0,0 +1,63 @@ +/*\ +title: test-popup.js +type: application/javascript +tags: [[$:/tags/test-spec]] + +Tests some utility function of the Popup prototype. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +describe("Popup tests", function() { + + it("parseCoordinates should parse valid coordinates", function() { + var popup = require("$:/core/modules/utils/dom/popup.js"); + + expect(popup.parseCoordinates("(1,2,3,4)")).toEqual({absolute: false, left: 1, top: 2, width: 3, height: 4}); + expect(popup.parseCoordinates("(1.5,2.6,3.7,4.8)")).toEqual({absolute: false, left: 1.5, top: 2.6, width: 3.7, height: 4.8}); + expect(popup.parseCoordinates("@(1,2,3,4)")).toEqual({absolute: true, left: 1, top: 2, width: 3, height: 4}); + expect(popup.parseCoordinates("@(1.5,2.6,3.7,4.8)")).toEqual({absolute: true, left: 1.5, top: 2.6, width: 3.7, height: 4.8}); + }); + + it("parseCoordinates should not parse invalid coordinates", function() { + var popup = require("$:/core/modules/utils/dom/popup.js"); + + expect(popup.parseCoordinates("#(1,2,3,4)")).toEqual(false); + expect(popup.parseCoordinates("(1,2,3,4")).toEqual(false); + expect(popup.parseCoordinates("(1,2,3)")).toEqual(false); + }); + + it("buildCoordinates should create valid coordinates", function() { + var popup = require("$:/core/modules/utils/dom/popup.js"); + + var coordinates = { + left: 1.5, + top: 2.6, + width: 3.7, + height: 4.8 + }; + + expect(popup.buildCoordinates(popup.coordinatePrefix.csOffsetParent, coordinates)).toEqual("(1.5,2.6,3.7,4.8)"); + expect(popup.buildCoordinates(popup.coordinatePrefix.csAbsolute, coordinates)).toEqual("@(1.5,2.6,3.7,4.8)"); + }); + + it("buildCoordinates should detect invalid input", function() { + var popup = require("$:/core/modules/utils/dom/popup.js"); + + var coordinates = { + left: "invalid", + top: 2.6, + width: 3.7, + height: 4.8 + }; + + expect(popup.buildCoordinates(popup.coordinatePrefix.csOffsetParent, coordinates)).toEqual("(0,0,0,0)"); + expect(popup.buildCoordinates("dummy", coordinates)).toEqual("(0,0,0,0)"); + }); +}); + +})(); diff --git a/editions/test/tiddlers/tests/test-prefixes-filter.js b/editions/test/tiddlers/tests/test-prefixes-filter.js index e32827f9f..a8d109d73 100644 --- a/editions/test/tiddlers/tests/test-prefixes-filter.js +++ b/editions/test/tiddlers/tests/test-prefixes-filter.js @@ -343,6 +343,9 @@ describe("'reduce' and 'intersection' filter prefix tests", function() { rootWidget.setVariable("add-price","[get[price]multiply{!!quantity}add]"); rootWidget.setVariable("num-items","[get[quantity]add]"); rootWidget.setVariable("join-with-commas","[compare:number:gt[0]thenaddsuffix[, ]addsuffixelse]"); + rootWidget.setVariable("undefined-variable","[]"); + rootWidget.setVariable("echo","$text$",[{name:"text"}],true); + rootWidget.setVariable("num-items-macro-param","[subfilteradd]"); expect(wiki.filterTiddlers("[tag[shopping]reduce]",anchorWidget).join(",")).toBe("22"); expect(wiki.filterTiddlers("[tag[shopping]reduce]",anchorWidget).join(",")).toBe("27.75"); @@ -351,6 +354,9 @@ describe("'reduce' and 'intersection' filter prefix tests", function() { expect(wiki.filterTiddlers("[tag[non-existent]reduce,[0]]",anchorWidget).join(",")).not.toBe("0"); expect(wiki.filterTiddlers("[tag[non-existent]reduce,[0]]",anchorWidget).length).toBe(0); expect(wiki.filterTiddlers("[tag[non-existent]reduceelse[0]]",anchorWidget).join(",")).toBe("0"); + // #7155 + expect(wiki.filterTiddlers("a +[reduce]",anchorWidget).join(",")).toBe(""); + expect(wiki.filterTiddlers("[tag[shopping]reduce]",anchorWidget).join(",")).toBe("22"); }); it("should handle the average operator", function() { @@ -392,10 +398,16 @@ describe("'reduce' and 'intersection' filter prefix tests", function() { rootWidget.setVariable("larger-than-18","[get[text]length[]compare:integer:gteq[18]]"); rootWidget.setVariable("nr","18"); rootWidget.setVariable("larger-than-18-with-var","[get[text]length[]compare:integer:gteq]"); + rootWidget.setVariable("undefined-variable","[]"); + rootWidget.setVariable("echo","$text$",[{name:"text"}],true); + rootWidget.setVariable("larger-than-18-macro-param","[subfilter]"); expect(wiki.filterTiddlers("[tag[textexample]] :filter[get[text]length[]compare:integer:gteq[18]]",anchorWidget).join(",")).toBe("Cheesecake,Chocolate Cake,Red wine"); expect(wiki.filterTiddlers("[tag[textexample]]",anchorWidget).join(",")).toBe("Cheesecake,Chocolate Cake,Red wine,Sparkling water"); expect(wiki.filterTiddlers("[tag[textexample]filter]",anchorWidget).join(",")).toBe("Cheesecake,Chocolate Cake,Red wine"); expect(wiki.filterTiddlers("[tag[textexample]filter]",anchorWidget).join(",")).toBe("Cheesecake,Chocolate Cake,Red wine"); + // #7155 + expect(wiki.filterTiddlers("a +[filter]",anchorWidget).join(",")).toBe("a"); + expect(wiki.filterTiddlers("[tag[textexample]filter]",anchorWidget).join(",")).toBe("Cheesecake,Chocolate Cake,Red wine"); }); it("should handle the :sort prefix", function() { @@ -422,6 +434,15 @@ describe("'reduce' and 'intersection' filter prefix tests", function() { expect(wiki.filterTiddlers("[tag[shopping]] :map[get[title]addprefix[-]addprefixaddprefix[of]addprefix]").join(",")).toBe("0of4-Brownies,1of4-Chick Peas,2of4-Milk,3of4-Rice Pudding"); }); + it("should handle the :then prefix", function() { + expect(wiki.filterTiddlers("[[one]] :then[[two]]").join(",")).toBe("two"); + expect(wiki.filterTiddlers("[[one]] :then[tag[shopping]]").join(",")).toBe("Brownies,Chick Peas,Milk,Rice Pudding"); + expect(wiki.filterTiddlers("[[one]] [[two]] [[three]] :then[[four]]").join(",")).toBe("four"); + expect(wiki.filterTiddlers("[[one]] :then[tag[nonexistent]]").join(",")).toBe("one"); + expect(wiki.filterTiddlers(":then[[two]]").length).toBe(0); + expect(wiki.filterTiddlers("[[notatiddler]is[tiddler]] :then[[two]]").length).toBe(0); + }); + it("should handle macro parameters for filter run prefixes",function() { var widget = require("$:/core/modules/widgets/widget.js"); var rootWidget = new widget.widget({ type:"widget", children:[ {type:"widget", children:[]} ] }, diff --git a/editions/test/tiddlers/tests/test-utils.js b/editions/test/tiddlers/tests/test-utils.js index 8b7630a54..91ddf86f4 100644 --- a/editions/test/tiddlers/tests/test-utils.js +++ b/editions/test/tiddlers/tests/test-utils.js @@ -48,6 +48,29 @@ describe("Utility tests", function() { expect($tw.utils.base64Decode($tw.utils.base64Encode(booksEmoji))).toBe(booksEmoji, "should round-trip correctly"); }); + it("should handle base64 encoding emojis in URL-safe variant", function() { + var booksEmoji = "📚"; + expect($tw.utils.base64Encode(booksEmoji, false, true)).toBe("8J-Tmg==", "if surrogate pairs are correctly treated as a single code unit then base64 should be 8J+Tmg=="); + expect($tw.utils.base64Decode("8J-Tmg==", false, true)).toBe(booksEmoji); + expect($tw.utils.base64Decode($tw.utils.base64Encode(booksEmoji, false, true), false, true)).toBe(booksEmoji, "should round-trip correctly"); + }); + + it("should handle base64 encoding binary data", function() { + var binaryData = "\xff\xfe\xfe\xff"; + var encoded = $tw.utils.base64Encode(binaryData,true); + expect(encoded).toBe("//7+/w=="); + var decoded = $tw.utils.base64Decode(encoded,true); + expect(decoded).toBe(binaryData, "Binary data did not round-trip correctly"); + }); + + it("should handle base64 encoding binary data in URL-safe variant", function() { + var binaryData = "\xff\xfe\xfe\xff"; + var encoded = $tw.utils.base64Encode(binaryData,true,true); + expect(encoded).toBe("__7-_w=="); + var decoded = $tw.utils.base64Decode(encoded,true,true); + expect(decoded).toBe(binaryData, "Binary data did not round-trip correctly"); + }); + it("should handle stringifying a string array", function() { var str = $tw.utils.stringifyList; expect(str([])).toEqual(""); @@ -188,4 +211,4 @@ describe("Utility tests", function() { }); -})(); +})(); \ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-widget.js b/editions/test/tiddlers/tests/test-widget.js index 19848e761..0d1351f31 100755 --- a/editions/test/tiddlers/tests/test-widget.js +++ b/editions/test/tiddlers/tests/test-widget.js @@ -143,7 +143,7 @@ describe("Widget module", function() { var wiki = new $tw.Wiki(); // Add a tiddler wiki.addTiddlers([ - {title: "TiddlerOne", text: "<$transclude tiddler='TiddlerTwo'/>\n"}, + {title: "TiddlerOne", text: "<$transclude tiddler='TiddlerTwo'/>"}, {title: "TiddlerTwo", text: "<$transclude tiddler='TiddlerOne'/>"} ]); // Test parse tree @@ -157,7 +157,7 @@ describe("Widget module", function() { // Render the widget node to the DOM var wrapper = renderWidgetNode(widgetNode); // Test the rendering - expect(wrapper.innerHTML).toBe("Recursive transclusion error in transclude widget\n"); + expect(wrapper.innerHTML).toBe("Recursive transclusion error in transclude widget"); }); it("should deal with SVG elements", function() { @@ -268,7 +268,7 @@ describe("Widget module", function() { expect(wrapper.innerHTML).toBe("

Happy Result

"); // This is important. $Let needs to be aware enough not to let its - // own variables interfere with its ability to recognize no change. + // own variables interfere with its ability to recognise no change. // Doesn't matter that nothing has changed, we just need to make sure // it recognizes that that its outward facing variables are unchanged // EVEN IF some intermediate variables did change, there's no need to @@ -527,6 +527,68 @@ describe("Widget module", function() { expect(wrapper.children[0].children[15].sequenceNumber).toBe(53); }); + var testListJoin = function(oldList, newList) { + return function() { + var wiki = new $tw.Wiki(); + // Add some tiddlers + wiki.addTiddler({title: "Numbers", text: "", list: oldList}); + var text = "<$list filter='[list[Numbers]]' variable='item' join=', '><>"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe("

" + oldList.split(' ').join(', ') + "

"); + // Change the list and ensure new rendering is still right + wiki.addTiddler({title: "Numbers", text: "", list: newList}); + refreshWidgetNode(widgetNode,wrapper,["Numbers"]); + expect(wrapper.innerHTML).toBe("

" + newList.split(' ').join(', ') + "

"); + } + } + + it("the list widget with join should update correctly when empty list gets one item", testListJoin("", "1")); + it("the list widget with join should update correctly when empty list gets two items", testListJoin("", "1 2")); + it("the list widget with join should update correctly when single-item list is appended to", testListJoin("1", "1 2")); + it("the list widget with join should update correctly when single-item list is prepended to", testListJoin("1", "2 1")); + it("the list widget with join should update correctly when list is appended", testListJoin("1 2 3 4", "1 2 3 4 5")); + it("the list widget with join should update correctly when last item is removed", testListJoin("1 2 3 4", "1 2 3")); + it("the list widget with join should update correctly when first item is inserted", testListJoin("1 2 3 4", "0 1 2 3 4")); + it("the list widget with join should update correctly when first item is removed", testListJoin("1 2 3 4", "2 3 4")); + it("the list widget with join should update correctly when first two items are swapped", testListJoin("1 2 3 4", "2 1 3 4")); + it("the list widget with join should update correctly when last two items are swapped", testListJoin("1 2 3 4", "1 2 4 3")); + it("the list widget with join should update correctly when last item is moved to the front", testListJoin("1 2 3 4", "4 1 2 3")); + it("the list widget with join should update correctly when last item is moved to the middle", testListJoin("1 2 3 4", "1 4 2 3")); + it("the list widget with join should update correctly when first item is moved to the back", testListJoin("1 2 3 4", "2 3 4 1")); + it("the list widget with join should update correctly when middle item is moved to the back", testListJoin("1 2 3 4", "1 3 4 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 1", testListJoin("1 3 4", "1 2 3")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 2", testListJoin("1 3 4", "1 3 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 3", testListJoin("1 3 4", "2 1 3")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 4", testListJoin("1 3 4", "2 3 1")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 5", testListJoin("1 3 4", "3 1 2")); + it("the list widget with join should update correctly when the last item disappears at the same time as other edits 6", testListJoin("1 3 4", "3 2 1")); + + var testCounterLast = function(oldList, newList) { + return function() { + var wiki = new $tw.Wiki(); + // Add some tiddlers + wiki.addTiddler({title: "Numbers", text: "", list: oldList}); + var text = "<$list filter='[list[Numbers]]' variable='item' counter='c'><><$text text={{{ [match[no]then[, ]] }}} />"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe("

" + oldList.split(' ').join(', ') + "

"); + // Append a number + wiki.addTiddler({title: "Numbers", text: "", list: newList}); + refreshWidgetNode(widgetNode,wrapper,["Numbers"]); + expect(wrapper.innerHTML).toBe("

" + newList.split(' ').join(', ') + "

"); + } + } + + it("the list widget with counter-last should update correctly when list is appended", testCounterLast("1 2 3 4", "1 2 3 4 5")); + it("the list widget with counter-last should update correctly when last item is removed", testCounterLast("1 2 3 4", "1 2 3")); + it("the list widget with counter-last should update correctly when first item is inserted", testCounterLast("1 2 3 4", "0 1 2 3 4")); + it("the list widget with counter-last should update correctly when first item is removed", testCounterLast("1 2 3 4", "2 3 4")); + it("should deal with the list widget followed by other widgets", function() { var wiki = new $tw.Wiki(); // Add some tiddlers @@ -683,7 +745,7 @@ describe("Widget module", function() { expect(wrapper.innerHTML).toBe("

New value

"); }); - it("should can mix setWidgets and macros when importing", function() { + it("should support mixed setWidgets and macros when importing", function() { var wiki = new $tw.Wiki(); // Add some tiddlers wiki.addTiddlers([ @@ -699,6 +761,20 @@ describe("Widget module", function() { expect(wrapper.innerHTML).toBe("

Aval Bval Cval

"); }); + it("should skip parameters widgets when importing", function() { + var wiki = new $tw.Wiki(); + // Add some tiddlers + wiki.addTiddlers([ + {title: "B", text: "<$parameters bee=nothing><$set name='B' value='Bval'>\n\ndummy text"}, + ]); + var text = "\\import B\n<>"; + var widgetNode = createWidgetNode(parseText(text,wiki),wiki); + // Render the widget node to the DOM + var wrapper = renderWidgetNode(widgetNode); + // Test the rendering + expect(wrapper.innerHTML).toBe("

Bval

"); + }); + it("can have more than one macroDef variable imported", function() { var wiki = new $tw.Wiki(); wiki.addTiddlers([ diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 7f1551c28..bc3d9acd8 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -19,7 +19,8 @@ describe("WikiText parser tests", function() { // Define a parsing shortcut var parse = function(text) { - return wiki.parseText("text/vnd.tiddlywiki",text).tree; + var tree = wiki.parseText("text/vnd.tiddlywiki",text).tree; + return tree; }; it("should parse tags", function() { @@ -114,7 +115,70 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [ { type : 'set', attributes : { name : { type : 'string', value : 'myMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}]}] + + ); + }); + + it("should parse procedure definitions with no parameters", function() { + expect(parse("\\procedure myMacro()\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse single line procedure definitions with no parameters", function() { + expect(parse("\\procedure myMacro() nothing\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse procedure definitions with parameters", function() { + expect(parse("\\procedure myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[{"name":"one"},{"name":"two"},{"name":"three"},{"name":"four","default":"elephant"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isProcedureDefinition":true}] + + ); + }); + + it("should parse procedure definitions", function() { + expect(parse("\\procedure myMacro(one:'Jaguar')\n<$text text=<>/>\n\\end\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"<$text text=<>/>"}},"children":[],"params":[{"name":"one","default":"Jaguar"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"<$text text=<>/>"}],"isProcedureDefinition":true}] + + ); + + }); it("should parse function definitions with no parameters", function() { + expect(parse("\\function myMacro()\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse single line function definitions with no parameters", function() { + expect(parse("\\function myMacro() nothing\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse function definitions with parameters", function() { + expect(parse("\\function myMacro(one,two,three,four:elephant)\nnothing\n\\end\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[{"name":"one"},{"name":"two"},{"name":"three"},{"name":"four","default":"elephant"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"isFunctionDefinition":true}] + + ); + }); + + it("should parse function definitions", function() { + expect(parse("\\function myMacro(one:'Jaguar')\n<$text text=<>/>\n\\end\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"<$text text=<>/>"}},"children":[],"params":[{"name":"one","default":"Jaguar"}],"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"<$text text=<>/>"}],"isFunctionDefinition":true}] ); }); @@ -122,7 +186,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [ { type : 'set', attributes : { name : { type : 'string', value : 'aMacro' }, value : { type : 'string', value : 'nothing' } }, children : [ ], params : [ ], isMacroDefinition : true } ] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}]}] ); }); @@ -143,38 +207,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 35, children: [ { type: 'macrocall', start: 0, params: [ ], name: 'john', end: 8 }, { type: 'macrocall', start: 8, params: [ ], name: 'paul', end: 16 }, { type: 'macrocall', start: 16, params: [ ], name: 'george', end: 26 }, { type: 'macrocall', start: 26, params: [ ], name: 'ringo', end: 35 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{ type: 'element', tag: 'p', start: 0, end: 92, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', name: 'john', start: 5, params: [ { type: 'macro-parameter', start: 11, value: 'val1', name: 'one', end: 20 }, { type: 'macro-parameter', start: 20, value: 'val "2"', name: 'two', end: 35 }, { type: 'macro-parameter', start: 35, value: 'val \'3\'', name: 'three', end: 52 }, { type: 'macro-parameter', start: 52, value: 'val 4"5\'', name: 'four', end: 73 }, { type: 'macro-parameter', start: 73, value: 'val 5', name: 'five', end: 89 } ], end: 92 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 27, children: [ { type: 'text', text: 'ignored << carrots ', start: 0, end: 19 }, { type: 'macrocall', name: 'john', start: 19, params: [ ], end: 27 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 14, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', name: '>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 15, children: [ { type: 'text', text: 'before\n', start: 0, end: 7 }, { type: 'macrocall', start: 7, params: [ ], name: 'john', end: 15 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 9, children: [ { type: 'macrocall', start: 0, params: [ ], name: 'john', end: 8 }, { type: 'text', text: ' ', start: 8, end: 9 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 34, children: [ { type: 'text', text: 'text ', start: 0, end: 5 }, { type: 'macrocall', start: 5, params: [ { type: 'macro-parameter', start: 12, value: 'my <>', name: 'one', end: 31 } ], name: 'outie', end: 34 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -183,37 +247,37 @@ describe("WikiText parser tests", function() { it("should parse block macro calls", function() { expect(parse("<>\n<>\r\n<>\n<>")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ ], end: 8, isBlock: true }, { type: 'macrocall', start: 9, name: 'paul', params: [ ], end: 17, isBlock: true }, { type: 'macrocall', start: 19, name: 'george', params: [ ], end: 29, isBlock: true }, { type: 'macrocall', start: 30, name: 'ringo', params: [ ], end: 39, isBlock: true } ] + [ { type: 'transclude', start: 0, attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: 'transclude', start: 9, attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: 'transclude', start: 19, attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: 'transclude', start: 30, attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] ); expect(parse("<>")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ { type: 'macro-parameter', start: 6, value: 'val1', name: 'one', end: 15 }, { type: 'macro-parameter', start: 15, value: 'val "2"', name: 'two', end: 30 }, { type: 'macro-parameter', start: 30, value: 'val \'3\'', name: 'three', end: 47 }, { type: 'macro-parameter', start: 47, value: 'val 4"5\'', name: 'four', end: 68 }, { type: 'macro-parameter', start: 68, value: 'val 5', name: 'five', end: 84 }], end: 87, isBlock: true } ] + [{"type":"transclude","start":0,"end":87,"attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":6,"end":15},"two":{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},"three":{"name":"three","type":"string","value":"val '3'","start":30,"end":47},"four":{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},"five":{"name":"five","type":"string","value":"val 5","start":68,"end":84}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":6,"end":15},{"name":"two","type":"string","value":"val \"2\"","start":15,"end":30},{"name":"three","type":"string","value":"val '3'","start":30,"end":47},{"name":"four","type":"string","value":"val 4\"5'","start":47,"end":68},{"name":"five","type":"string","value":"val 5","start":68,"end":84}],"isBlock":true}] ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'macrocall', start: 12, params: [ ], name: 'john', end: 20, isBlock: true } ] + [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'macrocall', start: 8, name: 'john', params: [ ], end: 16, isBlock: true } ] + [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'macrocall', start: 0, name: 'john', params: [ ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: 'transclude', start: 0, attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 11, value: '\n\nwikitext\n', name: 'arg', end: 33 } ], name: 'multiline', end: 36, isBlock: true }] + [{"type":"transclude","start":0,"end":36,"attributes":{"$variable":{"name":"$variable","type":"string","value":"multiline"},"arg":{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}},"orderedAttributes":[{"name":"$variable","type":"string","value":"multiline"},{"name":"arg","type":"string","value":"\n\nwikitext\n","start":11,"end":33}],"isBlock":true}] ); expect(parse("<>' >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 7, value: 'my <>', name: 'one', end: 26 } ], name: 'outie', end: 29, isBlock: true } ] + [ { type: 'transclude', start: 0, attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] ); }); @@ -221,23 +285,23 @@ describe("WikiText parser tests", function() { it("should parse tricky macrocall parameters", function() { expect(parse("<am>>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'pa>am', end: 12 } ], name: 'john', end: 14, isBlock: true } ] + [{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"pa>am","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"pa>am","start":6,"end":12}],"isBlock":true}] ); expect(parse("< >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'param>', end: 13 } ], name: 'john', end: 16, isBlock: true } ] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"param>","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param>","start":6,"end":13}],"isBlock":true}] ); expect(parse("<>>")).toEqual( - [ { type: 'element', tag: 'p', start: 0, end: 15, children: [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'param', end: 12 } ], name: 'john', end: 14 }, { type: 'text', text: '>', start: 14, end: 15 } ] } ] + [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":14,"attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed expect(parse("<=4 >>")).toEqual( - [ { type: 'macrocall', start: 0, params: [ { type: 'macro-parameter', start: 6, value: 'var>=4', end: 13 } ], name: 'john', end: 16, isBlock: true } ] + [{"type":"transclude","start":0,"end":16,"attributes":{"0":{"name":"0","type":"string","value":"var>=4","start":6,"end":13},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"var>=4","start":6,"end":13}],"isBlock":true}] ); diff --git a/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js b/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js index b37f402cc..39f061d11 100644 --- a/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js +++ b/editions/test/tiddlers/tests/test-wikitext-tabs-macro.js @@ -1,7 +1,7 @@ /*\ title: test-wikitext-tabs-macro.js type: application/javascript -tags: [[$:/tags/test-spec]] +tags: [[$:/tags/test-spec-disabled]] Tests the core tabs macro by comparing the HTML output with a stored template. Intended to permit future readability improvements. @@ -74,7 +74,7 @@ describe("Tabs-macro HTML tests", function() { expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal")).toBe(expected.fields.text.replace(/\n/g,"")); }); - it("should render 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() { + it("should render all 'horizontal' tabs from v5.2.2 and up with whitespace trim", function() { expect(wiki.renderTiddler("text/html","test-tabs-macro-horizontal-all")).toBe(expectedAll.fields.text.replace(/\n/g,"")); }); diff --git a/editions/test/tiddlers/tests/test-wikitext.js b/editions/test/tiddlers/tests/test-wikitext.js index 4cab566da..eddef73f7 100644 --- a/editions/test/tiddlers/tests/test-wikitext.js +++ b/editions/test/tiddlers/tests/test-wikitext.js @@ -43,17 +43,7 @@ describe("WikiText tests", function() { expect(wiki.renderTiddler("text/html","TiddlerThree")).toBe("

The speed of sound

The light of speed

"); }); it("should support attributes specified as macro invocations", function() { - expect(wiki.renderTiddler("text/html","TiddlerFour")).toBe("

This is a link

"); - }); - it("should identify wikiwords to automatically link", function() { - expect(wiki.renderText("text/html","text/vnd-tiddlywiki","No wikilinks here").indexOf("This is a link

"); }); it("handles style wikitext notation", function() { expect(wiki.renderText("text/html","text/vnd-tiddlywiki","@@.myclass\n!header\n@@")).toBe("

header

"); diff --git a/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png b/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png new file mode 100644 index 000000000..29a70a1c3 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png.meta b/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png.meta new file mode 100644 index 000000000..b374371bf --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Asteroid (253) Mathilde Image.png.meta @@ -0,0 +1,3 @@ +title: Asteroid (253) Mathilde Image +type: image/png +tags: Image diff --git a/editions/tour/tiddlers/Solar System/Asteroid.tid b/editions/tour/tiddlers/Solar System/Asteroid.tid new file mode 100644 index 000000000..e1b3a0f29 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Asteroid.tid @@ -0,0 +1,17 @@ +created: 20230720112554020 +modified: 20230720112827830 +title: Asteroid +type: text/vnd.tiddlywiki +tags: [[Solar System]] + +[img class=hero-image [Asteroid (253) Mathilde Image]] + +An asteroid is a space rock. It is a small object in the [[Solar System]] that travels around the [[Sun]]. It is like a [[planet|Planet]] but smaller. They range from very small (smaller than a car) to 600 miles (1000 km) across. A few asteroids have asteroid moons. + +The name "asteroid" means "like a star" in the ancient Greek language. Asteroids may look like small stars in the sky, but they really do move around the [[Sun]], while stars only seem to move because the [[Earth]] spins. Like [[planets|Planet]], asteroids do not make their own light. Because of this, some people think "asteroids" is not a good name, and think that the name "planetoid" ("like a planet") would be a better name. + +Giuseppe Piazzi found the first asteroid, in 1801. He called it Ceres, and it is the biggest object in the asteroid belt. Others, like Juno, Pallas, and Vesta were found later. In the 1850s so many had been found, that they were numbered by a Minor planet designation starting with 1 Ceres. Today, astronomers using computerized telescopes find thousands of asteroids every month. Asteroid impact prediction is one of the purposes. + +Asteroids are the leftover rock and other material from the formation of the [[Solar System]]. These rocks were too small to come together to make a [[planet|Planet]]. Some are made of carbon or metal. Depending on what's on the surface, they are classified into various asteroid spectral types including Type M (metal), Type S (stone), and Type C (carbon). + +Most asteroids in our [[Solar System]] are in the asteroid belt between [[Mars]] and [[Jupiter]]. Many are not in the main asteroid belt. The ones that come close to [[Earth]] are called Near-Earth asteroids. Many scientists think asteroids striking the [[Earth]] killed off all the dinosaurs and caused some of the other extinction events. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Comet Image.png b/editions/tour/tiddlers/Solar System/Comet Image.png new file mode 100644 index 000000000..5223b95e3 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Comet Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Comet Image.png.meta b/editions/tour/tiddlers/Solar System/Comet Image.png.meta new file mode 100644 index 000000000..8972522f3 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Comet Image.png.meta @@ -0,0 +1,3 @@ +title: Comet Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Comet.tid b/editions/tour/tiddlers/Solar System/Comet.tid new file mode 100644 index 000000000..1555b6c90 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Comet.tid @@ -0,0 +1,15 @@ +created: 20230720113501352 +modified: 20230720113633994 +title: Comet +type: text/vnd.tiddlywiki +tags: [[Solar System]] + +[img class=hero-image [Comet Image]] + +A comet is a ball of mostly ice that moves around in outer space. Comets are often described as "dirty snowballs". They are very different from [[asteroids|Asteroid]]. The orbital inclinations of comets are usually high and not near the ecliptic where most [[solar system|Solar System]] objects are found. Most of them are long-period comets and come from the [[Kuiper belt]]. That is very far away from the [[Sun]], but some of them also come near enough to [[Earth]] for us to see at night. + +They have long "tails", because the [[Sun]] melts the ice. A comet's tail does not trail behind it, but points directly away from the [[Sun]], because it is blown by the solar wind. The hard centre of the comet is the nucleus. It is one of the blackest things (lowest albedo) in the [[solar system|Solar System]]. When light shone on the nucleus of Halley's Comet, the comet reflected only 4% of the light back to us. + +Periodic comets visit again and again. Non-periodic or single-apparition comets visit only once. + +Comets sometimes break up, as Comet Biela did in the 19th century. Comet Shoemaker-Levy 9 broke up, and the pieces hit [[Jupiter]] in 1994. Some comets orbit (go around) together in groups. Astronomers think these comets are broken pieces that used to be one object. diff --git a/editions/tour/tiddlers/Solar System/Earth Image.png b/editions/tour/tiddlers/Solar System/Earth Image.png new file mode 100644 index 000000000..d2584076c Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Earth Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Earth Image.png.meta b/editions/tour/tiddlers/Solar System/Earth Image.png.meta new file mode 100644 index 000000000..e699640b6 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Earth Image.png.meta @@ -0,0 +1,3 @@ +title: Earth Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Earth's Moon Image.png b/editions/tour/tiddlers/Solar System/Earth's Moon Image.png new file mode 100644 index 000000000..f33afc953 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Earth's Moon Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Earth's Moon Image.png.meta b/editions/tour/tiddlers/Solar System/Earth's Moon Image.png.meta new file mode 100644 index 000000000..855226d8f --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Earth's Moon Image.png.meta @@ -0,0 +1,3 @@ +title: Earth's Moon Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Earth's Moon.tid b/editions/tour/tiddlers/Solar System/Earth's Moon.tid new file mode 100644 index 000000000..6ef234fb0 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Earth's Moon.tid @@ -0,0 +1,10 @@ +created: 20230720105302348 +modified: 20230720105451528 +title: Earth's Moon +type: text/vnd.tiddlywiki + +[img class=hero-image [Earth's Moon Image]] + +The Moon is [[Earth]]'s only natural satellite. We usually see it in the night sky and also during the day. Some other planets also have moons or natural satellites. + +Our moon is about one-fourth of the width of the [[Earth]]. Because it is far away it looks small, about half a degree wide. The gravity on the moon is one-sixth of the [[Earth]]'s gravity. It means that something will be one-sixth as heavy on the Moon than on [[Earth]]. The Moon is a rocky and dusty place. It moves slowly away from the [[Earth]] at a rate of 3.8 cm per year, due to the effect of tidal dissipation. diff --git a/editions/tour/tiddlers/Solar System/Earth.tid b/editions/tour/tiddlers/Solar System/Earth.tid new file mode 100644 index 000000000..1c467fb9d --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Earth.tid @@ -0,0 +1,21 @@ +created: 20230720102439731 +modified: 20230720105223869 +title: Earth +type: text/vnd.tiddlywiki +tags: Planet [[Rocky]] + +[img class=hero-image [Earth Image]] + +Earth is the third planet from the [[Sun]] in the [[Solar System]]. It is the only planet known to have life on it. The Earth formed about 4.5 billion years ago. It is one of four rocky planets on the inner side of the [[Solar System]]. The other three are [[Mercury]], [[Venus]], and [[Mars]]. + +The large mass of the [[Sun]] keeps the Earth in orbit through the force of gravity. Earth also turns around in space, so that different parts face the Sun at different times. Earth goes around the [[Sun]] once (one year) for every 365​1⁄4 times it turns around (one day). + +Earth is the only planet in the [[Solar System]] that has a large amount of liquid water on its surface. About 74% of the surface of Earth is covered by liquid or frozen water. Because of this, people sometimes call it the blue planet. + +Because of its water, Earth is home to millions of species of plants and animals which need water to survive. The things that live on Earth have changed its surface greatly. For example, early cyanobacteria changed the air and gave it oxygen. The living part of Earth's surface is called the "biosphere". + +Earth is one of the eight planets in the [[Solar System]]. There are also thousands of small bodies which move around the [[Sun]]. The [[Solar System]] is moving through the Orion Arm of the [[Milky Way]] galaxy, and will be for about the next 10,000 years. + +Earth is about 150,000,000 kilometres or 93,000,000 miles away from the [[Sun]] (this distance is called an "Astronomical Unit"). It moves on its orbit at an average speed of about 30 km/s (19 mi/s). Earth turns all the way around about 365​1⁄4 times in the time it takes for Earth to go all the way around the [[Sun]]. To make up this extra bit of a day every year, an additional day is used every four years. This is named a "leap year". + +The [[Moon|Earth's Moon]] goes around Earth at an average distance of 400,000 kilometres or 250,000 miles. It is locked to Earth, so that it always has the same half facing Earth; the other half is called the "dark side of the moon". It takes about 27​1⁄3 days for the [[Moon|Earth's Moon]] to go all the way around Earth, but because Earth is moving around the [[Sun]] at the same time, it takes about 29​1⁄2 days for the [[Moon|Earth's Moon]] to go from dark to bright to dark again. This is where the word "month" came from, even though most months now have 30 or 31 days. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Jupiter Image.png b/editions/tour/tiddlers/Solar System/Jupiter Image.png new file mode 100644 index 000000000..933f1c115 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Jupiter Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Jupiter Image.png.meta b/editions/tour/tiddlers/Solar System/Jupiter Image.png.meta new file mode 100644 index 000000000..472a37e54 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Jupiter Image.png.meta @@ -0,0 +1,3 @@ +title: Jupiter Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Jupiter.tid b/editions/tour/tiddlers/Solar System/Jupiter.tid new file mode 100644 index 000000000..54ef1904c --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Jupiter.tid @@ -0,0 +1,15 @@ +created: 20230720103949854 +modified: 20230720104126047 +title: Jupiter +type: text/vnd.tiddlywiki +tags: Planet [[Gas Giant]] + +[img class=hero-image [Jupiter Image]] + +Jupiter is the largest planet in the [[Solar System]]. It is the fifth planet from the [[Sun]]. Jupiter is a gas giant because it is so large, and made mostly of gas. The other gas giants in the Solar System are [[Saturn]], [[Uranus]], and [[Neptune]]. + +Jupiter's mass is about 318 times the mass of [[Earth]]. This is more than twice the mass of all the other planets in the [[Solar System]] put together. + +Jupiter can be seen even without using a telescope. It is the third brightest object in the night sky. Only the [[Earth's Moon]] and [[Venus]] are brighter. The ancient Romans named the planet after their King of the Gods, Jupiter (Latin: Iuppiter). + +Jupiter has 95 known moons. About 75 of them are very small—less than five kilometres wide. The four largest moons of Jupiter are Io, Europa, Ganymede, and Callisto. They are called the Galilean moons because Galileo Galilei discovered them. Ganymede is the largest moon in the Solar System. Its diameter is larger than that of the planet [[Mercury]]. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Kuiper belt.tid b/editions/tour/tiddlers/Solar System/Kuiper belt.tid new file mode 100644 index 000000000..578fa81a0 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Kuiper belt.tid @@ -0,0 +1,12 @@ +created: 20230720113703253 +modified: 20230720113733279 +title: Kuiper belt +type: text/vnd.tiddlywiki + +The Kuiper belt is an area of the [[Solar System]] beyond the orbit of [[Neptune]] (at 30 astronomical units) to 50 AU from the [[Sun]]. + +The objects within the Kuiper Belt together with the members of the scattered disk beyond, are together called trans-Neptunian. + +Many objects such as dwarf planets in the Kuiper belt are much bigger than the ones in the asteroid belt and are round. At least some Kuiper belt objects are icebound. + +The first objects in the Kuiper belt to be found were [[Pluto]] and Charon (moon) but the belt was only identified and named in 1992 when more Kuiper belt objects (KBOs) were found. A few thousand have since been discovered and more than 70,000 KBOs over 100 km (62 mi) in diameter are thought to exist. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Mars Image.png b/editions/tour/tiddlers/Solar System/Mars Image.png new file mode 100644 index 000000000..32ffaa966 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Mars Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Mars Image.png.meta b/editions/tour/tiddlers/Solar System/Mars Image.png.meta new file mode 100644 index 000000000..bdd350430 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Mars Image.png.meta @@ -0,0 +1,5 @@ +created: 20230720103818354 +modified: 20230720103822277 +title: Mars Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Mars.tid b/editions/tour/tiddlers/Solar System/Mars.tid new file mode 100644 index 000000000..34ab6d138 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Mars.tid @@ -0,0 +1,11 @@ +created: 20230720103800905 +modified: 20230720103915592 +title: Mars +type: text/vnd.tiddlywiki +tags: Planet [[Rocky]] + +[img class=hero-image [Mars Image]] + +Mars is the fourth planet from the [[Sun]] in the [[Solar System]] and the second-smallest planet. Mars is a terrestrial planet with polar ice caps of frozen water and carbon dioxide. It has the largest volcano in the [[Solar System]], and some very large impact craters. Mars is named after the mythological Roman god of war because it appears of red color. + +Space probes such as the Viking program landers are the main tools for the exploration of Mars. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Mercury Image.png b/editions/tour/tiddlers/Solar System/Mercury Image.png new file mode 100644 index 000000000..7d92260b5 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Mercury Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Mercury Image.png.meta b/editions/tour/tiddlers/Solar System/Mercury Image.png.meta new file mode 100644 index 000000000..3ff1fd022 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Mercury Image.png.meta @@ -0,0 +1,3 @@ +title: Mercury Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Mercury.tid b/editions/tour/tiddlers/Solar System/Mercury.tid new file mode 100644 index 000000000..2df1fc653 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Mercury.tid @@ -0,0 +1,21 @@ +created: 20230720101415532 +modified: 20230720101809366 +title: Mercury +type: text/vnd.tiddlywiki +tags: Planet [[Rocky]] + +[img class=hero-image [Mercury Image]] + +Mercury is the smallest planet in the [[Solar System]]. It is the closest planet to the [[Sun]]. It makes one trip around the Sun once every 87.969 days. + +Mercury is bright when we can see it from [[Earth]]. It has an apparent magnitude ranging from −2.0 to 5.5. It cannot be seen easily because it is usually too close to the [[Sun]]. Because of this, Mercury can only be seen in the morning or evening twilight or when there is a solar eclipse. + +Less is known about Mercury than about other planets of our [[Solar System]]. Even with telescopes only a small, bright crescent can be seen. It is also hard to put a satellite in orbit around it. Two spacecraft have visited Mercury. The first one was Mariner 10. It only made a map of about 45% of the Mercury's surface from 1974 to 1975. The second is the MESSENGER spacecraft, which finished mapping Mercury in March 2013. + +Mercury looks like [[Earth's Moon]]. It has many craters and smooth plains. It has no moons and little atmosphere as we know it. However, Mercury does have an extremely thin atmosphere, known as an exosphere. Mercury has a large iron core. Because of this Mercury has a magnetic field about 1% as strong as that of the Earth. It is a very dense planet because its core is large. + +Temperature at the surface can be anywhere from about 90 to 700 K (−183 °C to 427 °C, −297 °F to 801 °F), with the subsolar point being the hottest and the bottoms of craters near the poles being the coldest. + +Known sightings of Mercury date back to at least the first millennium BC. Before the 4th century BC, Greek astronomers thought that Mercury was two different objects: The one that they were only able at sunrise, they called Apollo; the other one that they were only able to see at sunset, they called Hermes. The English name for the planet is from the Romans, who named it after the Roman god Mercury. The symbol for Mercury is based on Hermes' staff. + +Even though Mercury is the closest planet to the [[Sun]], it is not the hottest. This is because it has no greenhouse effect. The heat that the [[Sun]] gives it, quickly escapes into space. The hottest planet is [[Venus]]. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Milky Way Image.png b/editions/tour/tiddlers/Solar System/Milky Way Image.png new file mode 100644 index 000000000..a408977b1 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Milky Way Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Milky Way Image.png.meta b/editions/tour/tiddlers/Solar System/Milky Way Image.png.meta new file mode 100644 index 000000000..ba0727bb8 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Milky Way Image.png.meta @@ -0,0 +1,5 @@ +created: 20230720095228607 +modified: 20230720095237609 +title: Milky Way Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Milky Way.tid b/editions/tour/tiddlers/Solar System/Milky Way.tid new file mode 100644 index 000000000..353611a9d --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Milky Way.tid @@ -0,0 +1,14 @@ +created: 20230720095039202 +modified: 20230720095530636 +title: Milky Way +type: text/vnd.tiddlywiki + +[img class=hero-image [Milky Way Image]] + +The Milky Way is our home galaxy. It contains around 400 billion stars, including our [[Sun]]. + +The Milky Way has a diameter of about 170,000 or 200,000 light years, and is a barred spiral galaxy. The idea that the Milky Way is made of stars goes back to the Ancient Greek philosopher Democritus. + +The Milky Way has three main parts: a disk, where the [[Solar System]] is, a bulge at the core, and an outer halo all around it. Although the word "disk" suggests it is flat, the Milky Way is actually not quite flat. It is slightly warped and twisted. + +This galaxy belongs to the Local Group of three large galaxies and over 50 smaller galaxies. The Milky Way is one of the largest galaxies in the group, second to the Andromeda Galaxy. Its closest neighbour is the Canis Major Dwarf Galaxy, which is about 25,000 light years away from the Earth. The Andromeda Galaxy is moving towards the Milky Way Galaxy, and will collide with it in about 3.75 billion years. The Andromeda Galaxy moves with a speed of about 1,800 kilometres per minute. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Moon.tid b/editions/tour/tiddlers/Solar System/Moon.tid new file mode 100644 index 000000000..84dc3e8be --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Moon.tid @@ -0,0 +1,9 @@ +created: 20230720113324534 +modified: 20230720113416564 +title: Moon +type: text/vnd.tiddlywiki +tags: [[Solar System]] + +Bodies which orbit [[planets|Planet]] are called moons. They vary in size. The [[Earth]] has only one moon. Some other planets have many moons, and some have none. When people write just "the moon", they are usually talking about the moon of the Earth. [[Earth's Moon]] is written with a capital letter, Moon. The Latin word for the moon is luna, which is why the adjective used to talk about the moon is "lunar". For example, lunar eclipse. + +Anything that goes around a planet is called a satellite. Moons are natural satellites. People also use rockets to send machines into orbit around the Earth. These machines are called artificial (man-made) satellites. diff --git a/editions/tour/tiddlers/Solar System/Neptune Image.png b/editions/tour/tiddlers/Solar System/Neptune Image.png new file mode 100644 index 000000000..de2fc62a5 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Neptune Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Neptune Image.png.meta b/editions/tour/tiddlers/Solar System/Neptune Image.png.meta new file mode 100644 index 000000000..85d72346a --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Neptune Image.png.meta @@ -0,0 +1,3 @@ +title: Neptune Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Neptune.tid b/editions/tour/tiddlers/Solar System/Neptune.tid new file mode 100644 index 000000000..f6aa264ab --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Neptune.tid @@ -0,0 +1,19 @@ +created: 20230720104752241 +modified: 20230720104941305 +title: Neptune +type: text/vnd.tiddlywiki +tags: Planet [[Gas Giant]] + +[img class=hero-image [Neptune Image]] + +Neptune is the eighth and farthest planet from the [[Sun]] in the [[Solar System]]. It is an ice giant. It is the fourth-largest planet in the system. Neptune has five rings. These rings are hard to see from the [[Earth]]. + +Neptune's mass is 17 times [[Earth]]'s mass and a little bit more than [[Uranus]]' mass. Neptune is denser and smaller than [[Uranus]]. Its greater mass makes its gravity make its atmosphere smaller and denser. + +It was named after the Roman god of the sea, Neptune. Neptune's astronomical symbol is ♆, the trident of the god Neptune. + +Neptune's atmosphere is mostly hydrogen and helium. It also contains small amounts of methane which makes the planet appear blue. Neptune's blue color is much darker than the color of [[Uranus]]. Neptune also has the strongest winds of any planet in the [[Solar System]], as high as 2,100 km/h or 1,300 mph. + +Urbain Le Verrier and John Couch Adams were the astronomers who discovered Neptune. Neptune was not discovered using a telescope. It was the first planet to be discovered using mathematics. In 1821, astronomers saw that [[Uranus]]' orbit was different from what they expected. Another nearby planet's mass was changing [[Uranus]]' orbit. They found Neptune was the cause. + +Voyager 2 visited Neptune on 25 August 1989. It was the only spacecraft to visit the planet. Neptune used to have a huge storm known as the "Great Dark Spot". Voyager 2 discovered the spot in 1989. The dark spot was not seen in 1994, but new spots were found since then. It is not known why the dark spot disappeared. Visits by other space probes have been planned. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Planet Image.png b/editions/tour/tiddlers/Solar System/Planet Image.png new file mode 100644 index 000000000..48f0f247d Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Planet Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Planet Image.png.meta b/editions/tour/tiddlers/Solar System/Planet Image.png.meta new file mode 100644 index 000000000..edb449743 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Planet Image.png.meta @@ -0,0 +1,3 @@ +title: Planet Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Planet.tid b/editions/tour/tiddlers/Solar System/Planet.tid new file mode 100644 index 000000000..b6fd010a3 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Planet.tid @@ -0,0 +1,17 @@ +created: 20230720112945287 +modified: 20230720113139369 +title: Planet +type: text/vnd.tiddlywiki +tags: [[Solar System]] + +[img class=hero-image [Planet Image]] + +A planet is a large object such as [[Venus]] or [[Earth]] that orbits a star. Planets are smaller than stars, and they do not make light. [[Jupiter]] is the biggest planet in the [[Solar System]], while the smallest planet in the [[Solar System]] is [[Mercury]]. + +Planets are shaped like a slightly squashed ball (called a spheroid). Objects that orbit planets are called satellites. A star and everything which orbits it are called a star system. + +There are eight planets in the [[Solar System]]. [[Pluto]] used to be called a planet, but in August 2006, the International Astronomical Union decided it was a dwarf planet instead. There are four more known dwarf planets in the [[Solar System]], Ceres, Makemake, Eris and Haumea. + +The name "planet" is from the Greek word πλανήτης (planetes), meaning "wanderers", or "things that move". Until the 1990s, people only knew the planets in the [[Solar System]]. + +4,905 extrasolar planets (exoplanets) have been discovered in 3,629 planetary systems (January 2022 data). The count includes 808 multi-planetary systems. Known exoplanets range in size from gas giants about twice as large as Jupiter down to just over the size of the [[Moon|Earth's Moon]]. About 100 of these planets are roughly the size as [[Earth]]. Nine of these orbit in the habitable zone of their star. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Pluto Image.png b/editions/tour/tiddlers/Solar System/Pluto Image.png new file mode 100644 index 000000000..826869ba4 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Pluto Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Pluto Image.png.meta b/editions/tour/tiddlers/Solar System/Pluto Image.png.meta new file mode 100644 index 000000000..8bb04416f --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Pluto Image.png.meta @@ -0,0 +1,3 @@ +title: Pluto Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Pluto.tid b/editions/tour/tiddlers/Solar System/Pluto.tid new file mode 100644 index 000000000..f8968bf03 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Pluto.tid @@ -0,0 +1,12 @@ +created: 20230720113803689 +modified: 20230720114100139 +title: Pluto +type: text/vnd.tiddlywiki + +[img class=hero-image [Pluto Image]] + +Pluto is a dwarf [[planet|Planet]] in the [[Solar System]]. Its formal name is 134340 Pluto, and its planetary symbol ⯓ or ♇. Pluto is the ninth largest body that moves around the [[Sun]]. Upon first being discovered, Pluto was considered a planet but was reclassified to a dwarf planet in 2006. It is the largest body in the [[Kuiper belt]]. + +Like other members of the [[Kuiper belt]], Pluto is mainly made of rock and ice. It is quite small. It is about a fifth (⅕) of the weight of the [[Earth's Moon]]. It is only a third (⅓) of its volume. Pluto is very far from the [[Sun]], so its temperature is very low. The average temperature on Pluto is -226 to -240 degrees Celsius. It has an odd orbit and this orbit is very sloped. It takes Pluto to 30 to 49 AU (4.4–7.4 billion km) from the [[Sun]]. This causes Pluto to sometimes go closer to the Sun than [[Neptune]]. + +Since it was discovered in 1930, Pluto was thought to be the [[Solar System]]'s ninth planet. In the late 1970s, the minor planet 2060 Chiron was found and people learned that Pluto had a small size. Later, in the early 21st century, the scattered disc object Eris and other objects like Pluto were discovered. Eris was initially believed to be 27% larger than Pluto, but was later found to be slightly smaller. On August 24, 2006, the International Astronomical Union (IAU) gave a definition to the word "planet" for the first time. By this definition, Pluto was not a planet anymore. It became a "dwarf planet" along with Eris and Ceres. After this, Pluto was put on the list of minor planets and was downgraded in 2006 by astronomer Michael E Brown. It was given the number 134340. Some scientists still think that Pluto should be classified as a planet. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Saturn Image.png b/editions/tour/tiddlers/Solar System/Saturn Image.png new file mode 100644 index 000000000..e2a73acd2 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Saturn Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Saturn Image.png.meta b/editions/tour/tiddlers/Solar System/Saturn Image.png.meta new file mode 100644 index 000000000..42f23a6b3 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Saturn Image.png.meta @@ -0,0 +1,3 @@ +title: Saturn Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Saturn.tid b/editions/tour/tiddlers/Solar System/Saturn.tid new file mode 100644 index 000000000..cbd0848ea --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Saturn.tid @@ -0,0 +1,17 @@ +created: 20230720104344173 +modified: 20230720104515376 +title: Saturn +type: text/vnd.tiddlywiki +tags: Planet [[Gas Giant]] + +[img class=hero-image [Saturn Image]] + +Saturn is the sixth planet from the [[Sun]] in the [[Solar System]]. + +Saturn is one of the four gas giant planets in the [[Solar System]], together with [[Jupiter]], [[Uranus]], and [[Neptune]]. It is the second largest planet in the [[Solar System]] ([[Jupiter]] is larger). + +Saturn was named after the Roman god Saturnus. He was considered to be the same as the Greek god Kronos. Saturn's symbol is ♄ which is the symbol of Saturnus' sickle. + +Inside Saturn is probably a core of iron, nickel, silicon and oxygen compounds, surrounded by a deep layer of metallic hydrogen, then a layer of liquid hydrogen and liquid helium and finally, an outer gaseous layer. + +Saturn has 145 known moons orbiting the planet. The largest moon is Titan. Titan is larger in volume than the planet [[Mercury]]. Titan is the second-largest moon in the [[Solar System]]. The largest moon is a moon of [[Jupiter]], Ganymede. There are also many rings around Saturn. These rings are made of ice with some rocks and dust. Some people think that that the rings were made by a moon impact or other event. Saturn is about 1,433,000,000 km (870,000,000 mi) on average from the [[Sun]]. Saturn takes 29.6 Earth years to move around the [[Sun]]. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Solar System Image.png b/editions/tour/tiddlers/Solar System/Solar System Image.png new file mode 100644 index 000000000..2cd156daf Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Solar System Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Solar System Image.png.meta b/editions/tour/tiddlers/Solar System/Solar System Image.png.meta new file mode 100644 index 000000000..7f9210e9f --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Solar System Image.png.meta @@ -0,0 +1,3 @@ +title: Solar System Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Solar System.tid b/editions/tour/tiddlers/Solar System/Solar System.tid new file mode 100644 index 000000000..9a73fe9ee --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Solar System.tid @@ -0,0 +1,18 @@ +created: 20230720093645837 +modified: 20230720112852404 +title: Solar System +type: text/vnd.tiddlywiki + +[img class=hero-image [Solar System Image]] + +The Solar System is the [[Sun]] and all the objects that orbit around it. The Sun is orbited by [[planets|Planet]], [[asteroids|Asteroid]], [[comets|Comet]] and other things. + +The Solar System is about 4.568 billion years old. The Sun formed by gravity in a large molecular cloud. It is mainly hydrogen, which it converts into helium through nuclear fusion. The planets are in a flattened orbiting disk. This disk was left over from the cloud that formed the Sun. Eventually, the gas and dust of the disk came together into planets. It is thought that almost all stars and their planets form this way. + +The Sun is a star. It makes up 99.9% of the Solar System's mass. This means that it has strong gravity. The other objects are pulled into orbit around the Sun. The Sun is mostly made out of hydrogen, and some helium and higher elements. All heavier elements, called metals in astronomy, account for less than 2% of the Sun's mass. Oxygen is about 1% of the Sun's mass. Iron (0.2%) is the most plentiful of the other elements. + +There are eight planets in the Solar System. From closest to farthest from the Sun, they are: [[Mercury]], [[Venus]], [[Earth]], [[Mars]], [[Jupiter]], [[Saturn]], [[Uranus]] and [[Neptune]]. The first four planets are called terrestrial planets. They are mostly made of rock and metal, and they are mostly solid. The last four planets are called gas giants. This is because they are much larger than other planets and are mostly made of gas. + +Six of the planets, and the six largest dwarf planets, are orbited by [[moons|Moon]]. There are more than 200 moons in the Solar System. [[Mercury]] and [[Venus]] have no moons, and [[Jupiter]] and [[Saturn]] have the largest number of moons. The largest moon is [[Ganymede]] which is a moon of [[Jupiter]]. [[Titan]] is one of [[Saturn]]’s moons. It is the only moon in the Solar System to have an atmosphere, which is mainly composed of nitrogen. + +The Solar System also contains other things. There are [[asteroid belts|Asteroid]], mostly between [[Mars]] and [[Jupiter]]. Further out than [[Neptune]], there is the [[Kuiper belt]] and the scattered disc. These areas have dwarf planets, including [[Pluto]], Makemake, Haumea, Ceres and Eris. There are thousands of very small objects in these areas. There are also [[comets|Comet]], centaurs, and interplanetary dust. diff --git a/editions/tour/tiddlers/Solar System/Sun Image.png b/editions/tour/tiddlers/Solar System/Sun Image.png new file mode 100644 index 000000000..66da3a30a Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Sun Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Sun Image.png.meta b/editions/tour/tiddlers/Solar System/Sun Image.png.meta new file mode 100644 index 000000000..0f4c217b0 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Sun Image.png.meta @@ -0,0 +1,5 @@ +created: 20230720095341229 +modified: 20230720095343728 +type: image/png +title: Sun Image +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Sun.tid b/editions/tour/tiddlers/Solar System/Sun.tid new file mode 100644 index 000000000..16996c886 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Sun.tid @@ -0,0 +1,17 @@ +created: 20230720094834001 +modified: 20230720095518349 +title: Sun +type: text/vnd.tiddlywiki +tags: [[Solar System]] + +[img class=hero-image [Sun Image]] + +The Sun, also known as Sol, is a star at the center of our [[solar system|Solar System]]. It is a yellow star that gives off different types of energy such as infrared energy (heat), ultraviolet light, radio waves and light. It also gives off a stream of particles, which reaches [[Earth]] as "solar wind". The source of all this energy is nuclear fusion. Nuclear fusion is the reaction in the star which turns hydrogen into helium and makes huge amounts of energy. It is a nearly perfect ball of hot plasma. + +The Sun is a star like many others in our [[Milky Way]] galaxy. The Sun is a type of star called a G-type main-sequence star based on its spectral class. + +The Sun has existed for a little over 4.5 billion years. It is going to continue for at least as long again. + +The Sun is about a hundred times as wide as the Earth. It has a mass of 1.9891×1030 kg. This is 333,000 times the mass of the [[Earth]]. 1.3 million [[Earths|Earth]] can fit inside the Sun. The Sun fuses about 600 million tons of hydrogen into helium every second. + +The Sun is the main source of energy for the [[Earth]]. This energy is made deep inside the Sun in a process called nuclear fusion. Four hydrogen atoms are fused together to make one helium atom. Some of the leftover matter turns into energy. This is the same way energy is released in a hydrogen bomb. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Uranus Image.png b/editions/tour/tiddlers/Solar System/Uranus Image.png new file mode 100644 index 000000000..717c12fe9 Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Uranus Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Uranus Image.png.meta b/editions/tour/tiddlers/Solar System/Uranus Image.png.meta new file mode 100644 index 000000000..412b2588a --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Uranus Image.png.meta @@ -0,0 +1,3 @@ +title: Uranus Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Uranus.tid b/editions/tour/tiddlers/Solar System/Uranus.tid new file mode 100644 index 000000000..273021788 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Uranus.tid @@ -0,0 +1,19 @@ +created: 20230720104606510 +modified: 20230720104721998 +title: Uranus +type: text/vnd.tiddlywiki +tags: Planet [[Gas Giant]] + +[img class=hero-image [Uranus Image]] + +Uranus is the seventh planet from the [[Sun]] in our [[Solar System]]. Like [[Neptune]], it is an ice giant. It is the third largest planet in the solar system. + +The planet is made of ice, gases and liquid metal. Its atmosphere contains hydrogen (1H), helium (2He) and methane. The temperature on Uranus is −197 °C (−322.6 °F; 76.1 K) near the top of its atmosphere, but its small solid core (about 55% the mass of [[Earth]]) is probably about 4,730 °C (8,540 °F; 5,000 K). + +The planet is tilted on its axis so much that it is sideways. It has five big moons, many small ones, and a small system of 13 planetary rings. + +The distance between Uranus and the [[Sun]] is about 2.8 billion km. Uranus completes its orbit around the [[Sun]] in 84 earth years. It completes a spin around its axis in 17 hours and 14 minutes. This means there are about 43,000 Uranian days in one Uranian year. + +Uranus was discovered in 1781. This planet can be seen with the naked eye under perfect conditions. John Flamsteed saw it decades earlier but mistook it for a star (34 Tauri). + +Uranus is named after Uranus, the Greek name of the Sumerian god Anu, who was a god of the sky. \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Venus Image.png b/editions/tour/tiddlers/Solar System/Venus Image.png new file mode 100644 index 000000000..665bb18db Binary files /dev/null and b/editions/tour/tiddlers/Solar System/Venus Image.png differ diff --git a/editions/tour/tiddlers/Solar System/Venus Image.png.meta b/editions/tour/tiddlers/Solar System/Venus Image.png.meta new file mode 100644 index 000000000..fc1bd8938 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Venus Image.png.meta @@ -0,0 +1,3 @@ +title: Venus Image +type: image/png +tags: Image \ No newline at end of file diff --git a/editions/tour/tiddlers/Solar System/Venus.tid b/editions/tour/tiddlers/Solar System/Venus.tid new file mode 100644 index 000000000..33a2c1b72 --- /dev/null +++ b/editions/tour/tiddlers/Solar System/Venus.tid @@ -0,0 +1,17 @@ +created: 20230720101839792 +modified: 20230720104223481 +title: Venus +type: text/vnd.tiddlywiki +tags: Planet [[Rocky]] + +[img class=hero-image [Venus Image]] + +Venus is the second planet from the [[Sun]]. Venus is the only planet in the [[Solar System]] that has a day longer than a year. The year length of Venus is 225 [[Earth]] days. The day length of Venus is 243 [[Earth]] days. + +Venus is a terrestrial planet because it has a solid, rocky surface like other planets in the inner [[Solar System]]. Astronomers have known Venus for thousands of years. The ancient Romans named it after their goddess Venus, goddess of love and beauty. + +Venus is the brightest thing in the night sky except for the Moon. It is sometimes called the morning star or the evening star as at some elongations it is easily seen just before the sun comes up in the morning. At other times, it can be seen just after the sun goes down in the evening. Venus comes closer to the [[Earth]] than any other planet does. + +Venus is sometimes called the sister planet of L as they are quite similar in size and gravity. In other ways the planets are very different. Venus' atmosphere (air) is mostly carbon dioxide with clouds of sulphuric acid. Sulphuric acid is a chemical that is poisonous to life. For this it is sometimes known as the Earth's "evil twin". + +The thick atmosphere makes it hard to see the surface. Until the late twentieth century many thought there might be life there. The pressure on Venus' surface is 92 times that of [[Earth]]. Venus is one of only 2 planets in the [[Solar System]] (the other being [[Mercury]]) that has no moons. Venus spins very slowly on its axis and it spins in the opposite direction to the other planets. \ No newline at end of file diff --git a/editions/tour/tiddlers/System/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid b/editions/tour/tiddlers/System/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid new file mode 100644 index 000000000..9fbacf686 --- /dev/null +++ b/editions/tour/tiddlers/System/$__themes_tiddlywiki_vanilla_options_sidebarlayout.tid @@ -0,0 +1,4 @@ +title: $:/themes/tiddlywiki/vanilla/options/sidebarlayout +type: text/vnd.tiddlywiki + +fluid-fixed \ No newline at end of file diff --git a/editions/tour/tiddlers/System/DefaultTiddlers.tid b/editions/tour/tiddlers/System/DefaultTiddlers.tid new file mode 100644 index 000000000..932e7d52c --- /dev/null +++ b/editions/tour/tiddlers/System/DefaultTiddlers.tid @@ -0,0 +1,4 @@ +title: $:/DefaultTiddlers + +[[HelloThere]] +[[Solar System]] diff --git a/editions/tour/tiddlers/System/HelloThere.tid b/editions/tour/tiddlers/System/HelloThere.tid new file mode 100644 index 000000000..c66875f68 --- /dev/null +++ b/editions/tour/tiddlers/System/HelloThere.tid @@ -0,0 +1,5 @@ +title: HelloThere + +Welcome to this TiddlyWiki about the [[Solar System]]. + +With many thanks to the [[Simple English Wikipedia|https://simple.wikipedia.org/]], the original source of this material. diff --git a/editions/tour/tiddlers/System/SiteSubtitle.tid b/editions/tour/tiddlers/System/SiteSubtitle.tid new file mode 100644 index 000000000..77b568672 --- /dev/null +++ b/editions/tour/tiddlers/System/SiteSubtitle.tid @@ -0,0 +1,2 @@ +title: $:/SiteSubitle +text: An Interactive Guide \ No newline at end of file diff --git a/editions/tour/tiddlers/System/SiteTitle.tid b/editions/tour/tiddlers/System/SiteTitle.tid new file mode 100644 index 000000000..a719f77f6 --- /dev/null +++ b/editions/tour/tiddlers/System/SiteTitle.tid @@ -0,0 +1,2 @@ +title: $:/SiteTitle +text: ~TiddlyWiki Tour \ No newline at end of file diff --git a/editions/tour/tiddlers/System/configAutoStartTour.tid b/editions/tour/tiddlers/System/configAutoStartTour.tid new file mode 100644 index 000000000..6bafd6d58 --- /dev/null +++ b/editions/tour/tiddlers/System/configAutoStartTour.tid @@ -0,0 +1,2 @@ +title: $:/config/AutoStartTour +text: yes diff --git a/editions/tour/tiddlers/System/styles.tid b/editions/tour/tiddlers/System/styles.tid new file mode 100644 index 000000000..04e9b94d2 --- /dev/null +++ b/editions/tour/tiddlers/System/styles.tid @@ -0,0 +1,9 @@ +title: $:/demoshow/styles +tags: [[$:/tags/Stylesheet]] + +\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline + +.hero-image { +max-width: 300px; +max-height: 300px; +} \ No newline at end of file diff --git a/editions/tour/tiddlywiki.info b/editions/tour/tiddlywiki.info new file mode 100644 index 000000000..1c6ce20dc --- /dev/null +++ b/editions/tour/tiddlywiki.info @@ -0,0 +1,16 @@ +{ + "description": "A step by step introduction to TiddlyWiki", + "plugins": [ + "tiddlywiki/tour", + "tiddlywiki/confetti", + "tiddlywiki/dynannotate" + ], + "themes": [ + "tiddlywiki/vanilla", + "tiddlywiki/snowwhite" + ], + "build": { + "index": [ + "--rendertiddler","$:/core/save/all","index.html","text/plain"] + } +} diff --git a/editions/translators/tiddlers/system/PageControlButtonsVisibility.multids b/editions/translators/tiddlers/system/PageControlButtonsVisibility.multids index 65f2405ec..714479946 100644 --- a/editions/translators/tiddlers/system/PageControlButtonsVisibility.multids +++ b/editions/translators/tiddlers/system/PageControlButtonsVisibility.multids @@ -13,4 +13,5 @@ core/ui/Buttons/more-page-actions: show core/ui/Buttons/new-journal: hide core/ui/Buttons/permaview: hide core/ui/Buttons/storyview: hide +core/ui/Buttons/layout: hide core/ui/Buttons/theme: hide diff --git a/editions/translators/tiddlywiki.info b/editions/translators/tiddlywiki.info index b08c5ceda..b2cc4f7ba 100644 --- a/editions/translators/tiddlywiki.info +++ b/editions/translators/tiddlywiki.info @@ -12,7 +12,6 @@ "de-CH", "de-DE", "el-GR", - "en-GB", "en-US", "es-ES", "fa-IR", diff --git a/editions/tw.org/tiddlers/$__favicon.ico.png b/editions/tw.org/tiddlers/$__favicon.ico.png index c6b279307..b147a217b 100644 Binary files a/editions/tw.org/tiddlers/$__favicon.ico.png and b/editions/tw.org/tiddlers/$__favicon.ico.png differ diff --git a/editions/tw.org/tiddlers/Fundraising.tid b/editions/tw.org/tiddlers/Fundraising.tid index 0ccc5736b..0c521caea 100644 --- a/editions/tw.org/tiddlers/Fundraising.tid +++ b/editions/tw.org/tiddlers/Fundraising.tid @@ -14,10 +14,10 @@ We do need a small amount of money on an ongoing basis to pay the costs of runni We use Open Collective to allow you to contribute towards these costs. You can contribute a one-off donation, or make an ongoing monthly commitment. Find out more: -https://opencollective.com/tiddlywikidotorg +https://opencollective.com/tiddlywiki !! Community Projects We also use Open Collective to raise funds to support the development of major new features, plugins or community infrastructure. These projects generally involve a small team of individuals getting together and making a proposal to the rest of the community. -For example, the [[File Upload Plugin Project|https://opencollective.com/tiddlywikidotorg/projects/tiddlywiki-file-upload]] aims to radically simplify working with attached images. +For example, the [[File Upload Plugin Project|https://opencollective.com/tiddlywiki/projects/tiddlywiki-file-upload]] aims to radically simplify working with attached images. diff --git a/editions/tw.org/tiddlywiki.info b/editions/tw.org/tiddlywiki.info index 8df5a0fb3..5e4202ccc 100644 --- a/editions/tw.org/tiddlywiki.info +++ b/editions/tw.org/tiddlywiki.info @@ -15,14 +15,14 @@ "--savetiddlers","[tag[external-image]]","images", "--setfield","[tag[external-image]]","_canonical_uri","$:/core/templates/canonical-uri-external-image","text/plain", "--setfield","[tag[external-image]]","text","","text/plain", - "--rendertiddler","$:/core/save/all","index.html","text/plain"], + "--render","$:/core/save/all","index.html","text/plain"], "favicon": [ "--savetiddler","$:/favicon.ico","favicon.ico"], "static": [ - "--rendertiddler","$:/core/templates/static.template.html","static.html","text/plain", - "--rendertiddler","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", - "--rendertiddlers","[!is[system]]","$:/core/templates/static.tiddler.html","static","text/plain", - "--rendertiddler","$:/core/templates/static.template.css","static/static.css","text/plain"] + "--render","$:/core/templates/static.template.html","static.html","text/plain", + "--render","$:/core/templates/alltiddlers.template.html","alltiddlers.html","text/plain", + "--render","[!is[system]]","[encodeuricomponent[]addprefix[static/]addsuffix[.html]]","text/plain","$:/core/templates/static.tiddler.html", + "--render","$:/core/templates/static.template.css","static/static.css","text/plain"] }, "config": { "retain-original-tiddler-path": true diff --git a/editions/tw5.com-docs/tiddlywiki.info b/editions/tw5.com-docs/tiddlywiki.info index bf8f1cac6..4d486267b 100644 --- a/editions/tw5.com-docs/tiddlywiki.info +++ b/editions/tw5.com-docs/tiddlywiki.info @@ -10,6 +10,6 @@ ], "build": { "index": [ - "--rendertiddler","$:/core/save/all","index.html","text/plain"] + "--render","$:/core/save/all","index.html","text/plain"] } } diff --git a/editions/tw5.com-server/tiddlers/system/favicon.ico b/editions/tw5.com-server/tiddlers/system/favicon.ico deleted file mode 100644 index 3765a9a88..000000000 Binary files a/editions/tw5.com-server/tiddlers/system/favicon.ico and /dev/null differ diff --git a/editions/tw5.com-server/tiddlers/system/favicon.ico.meta b/editions/tw5.com-server/tiddlers/system/favicon.ico.meta deleted file mode 100644 index 2f3e81713..000000000 --- a/editions/tw5.com-server/tiddlers/system/favicon.ico.meta +++ /dev/null @@ -1,2 +0,0 @@ -title: $:/favicon.ico -type: image/x-icon diff --git a/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png b/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png new file mode 100644 index 000000000..75be8e27d Binary files /dev/null and b/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png differ diff --git a/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png.meta b/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png.meta new file mode 100644 index 000000000..76d0be1a8 --- /dev/null +++ b/editions/tw5.com-server/tiddlers/system/tiddlywiki.com.server.png.meta @@ -0,0 +1,2 @@ +title: $:/favicon.ico +type: image/png diff --git a/editions/tw5.com/tiddlers/Tables in WikiText CSS Utility Classes.tid b/editions/tw5.com/tiddlers/Tables in WikiText CSS Utility Classes.tid new file mode 100644 index 000000000..14abc1c86 --- /dev/null +++ b/editions/tw5.com/tiddlers/Tables in WikiText CSS Utility Classes.tid @@ -0,0 +1,81 @@ +created: 20220817153236691 +modified: 20221010074314452 +tags: [[Tables in WikiText]] +title: Tables in WikiText CSS Utility Classes +type: text/vnd.tiddlywiki + +~WikiText tables can be styled by applying CSS classes. For basic information on wiktext tables and how to style them, see [[Tables in WikiText]]. + +{{Table Classes, Captions, Headers and Footers}} + +As seen above, the resulting table is left aligned and grows to fit the content. This is the browser default layout behaviour for tables. To get another behaviour, various CSS classes can be added into the "`k` row". + +! Utility Classes + +{{Utility Classes}} + +! Examples + +The following examples apply the style classes to tables but the "General Utility Classes" can as well be used on DIVs or other [[HTML block elements|HTML Block Elements]] + +!! Centred Table + +To center a table horizontally, use `tc-center`: + +<> + +!! Centred Table, 80% Width + +To add empty left and right margins to a table that is otherwise full-tiddler-width, you can use `tc-max-width-80` + +<> | +|<<.lorem>> |Cell4 | +|Header|Header|h +""">> + +!! Table with Maximum Width + +To expand a table to full tiddler width, use `tc-max-width` + +<> + +!! Table with First Column Minimum Width + +The following example shows a simple "form" where the first columns width is adjusted to its content by means of `tc-first-col-min-width` + +< | +|Cell3 |<$edit-text tiddler="$:/temp/test-table-input" field="text"/> | +""">> + +!! Table with Maximum Width ~TextWidgets + +Here, the previous "form" is styled further to give the [[TextWidget]]s full width by adding the class `tc-edit-max-width` + +< | +|Cell3 |<$edit-text tiddler="$:/temp/test-table-input" field="text"/> | +""">> + +!! Table with No Borders + +The following is a table with maximum width. It contains [[TextWidget]]s with maximum width. The first column is set to be minimum width. Further, all links in the first column are set to __not__ line break (wrap) regardless of window resize. + +< | +|^ [[Link to a tiddler]]
some more text|<$edit-text tiddler="$:/temp/test-table-input" field="text"/> | +""">> diff --git a/editions/tw5.com/tiddlers/community/editions/TiddlyResearch by Kebi.tid b/editions/tw5.com/tiddlers/_TiddlyStudy_ by Kebi.tid similarity index 79% rename from editions/tw5.com/tiddlers/community/editions/TiddlyResearch by Kebi.tid rename to editions/tw5.com/tiddlers/_TiddlyStudy_ by Kebi.tid index 680009c41..c1e50ae0a 100644 --- a/editions/tw5.com/tiddlers/community/editions/TiddlyResearch by Kebi.tid +++ b/editions/tw5.com/tiddlers/_TiddlyStudy_ by Kebi.tid @@ -1,8 +1,9 @@ created: 20210101162308245 -modified: 20210101201435693 +modified: 20230110220417543 tags: [[Community Editions]] -title: "TiddlyResearch" by Kebi -url: https://kebifurai.github.io/TiddlyResearch/ +title: "TiddlyStudy" by Kebi +type: text/vnd.tiddlywiki +url: https://postkevone.github.io/tiddlystudy/ A adaptation of TiddlyWiki perfect for using as a Notebook sysetem. diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico deleted file mode 100644 index 03a9b6ee9..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png new file mode 100644 index 000000000..c0ae6e696 Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png.meta similarity index 80% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png.meta index 53a3ac055..c83def11f 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/classic.tiddlywiki.com.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/classic.tiddlywiki.com -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico deleted file mode 100644 index 7ad263dad..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png new file mode 100644 index 000000000..8e4602dda Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png.meta similarity index 80% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png.meta index a21a05c4a..d53b194b7 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/links.tiddlywiki.org.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/links.tiddlywiki.org -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png new file mode 100644 index 000000000..881947506 Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png.meta new file mode 100644 index 000000000..aa3f9d11a --- /dev/null +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/markplace.png.meta @@ -0,0 +1,3 @@ +title: $:/_tw_shared/favicons/marketplace +type: image/png +tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico deleted file mode 100644 index b73f67d49..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png new file mode 100644 index 000000000..dd2cb686c Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png.meta similarity index 79% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png.meta index 4f14e4af1..0913aa504 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.dev.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/tiddlywiki.com.dev -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico deleted file mode 100644 index abf226e9b..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png new file mode 100644 index 000000000..d797bbe8d Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png.meta similarity index 78% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png.meta index ad4a92d3b..b884444c3 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/tiddlywiki.com -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico deleted file mode 100644 index 707c67577..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png new file mode 100644 index 000000000..bbf053e28 Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png.meta similarity index 81% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png.meta index a5d98ea5e..4757a18bc 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.prerelease.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/tiddlywiki.com.prerelease -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico deleted file mode 100644 index 6d8d018e9..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png new file mode 100644 index 000000000..38f661431 Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png.meta similarity index 80% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png.meta index ef6c637c9..9479c07b2 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.ico.meta +++ b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.com.upgrade.png.meta @@ -1,3 +1,3 @@ title: $:/_tw_shared/favicons/tiddlywiki.com.upgrade -type: image/x-icon +type: image/png tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.ico b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.ico deleted file mode 100644 index c6b279307..000000000 Binary files a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.ico and /dev/null differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.png b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.png new file mode 100644 index 000000000..b147a217b Binary files /dev/null and b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.png differ diff --git a/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.ico.meta b/editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.png.meta similarity index 100% rename from editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.ico.meta rename to editions/tw5.com/tiddlers/_tw_shared/favicons/tiddlywiki.org.png.meta diff --git a/editions/tw5.com/tiddlers/_tw_shared/sites/marketplace.tid b/editions/tw5.com/tiddlers/_tw_shared/sites/marketplace.tid new file mode 100644 index 000000000..53b14585d --- /dev/null +++ b/editions/tw5.com/tiddlers/_tw_shared/sites/marketplace.tid @@ -0,0 +1,6 @@ +title: $:/_tw_shared/sites/marketplace +tags: $:/tags/TiddlyWikiSites TiddlyWikiSitesMenu +caption: marketplace +description: Commercial Products and Services +url: https://talk.tiddlywiki.org/c/marketplace/22 +icon: $:/_tw_shared/favicons/marketplace diff --git a/editions/tw5.com/tiddlers/_tw_shared/tags-TiddlyWikiSites.tid b/editions/tw5.com/tiddlers/_tw_shared/tags-TiddlyWikiSites.tid index 0dadeb2e3..00e567510 100644 --- a/editions/tw5.com/tiddlers/_tw_shared/tags-TiddlyWikiSites.tid +++ b/editions/tw5.com/tiddlers/_tw_shared/tags-TiddlyWikiSites.tid @@ -1,3 +1,3 @@ title: $:/tags/TiddlyWikiSites -list: $:/_tw_shared/sites/tiddlywiki.com $:/_tw_shared/sites/tiddlywiki.org $:/_tw_shared/sites/talk.tiddlywiki.org $:/_tw_shared/sites/links.tiddlywiki.org $:/_tw_shared/sites/tiddlywiki.com.upgrade $:/_tw_shared/sites/tiddlywiki.com.dev $:/_tw_shared/sites/tiddlywiki.com.prerelease $:/_tw_shared/sites/classic.tiddlywiki.com +list: $:/_tw_shared/sites/tiddlywiki.com $:/_tw_shared/sites/tiddlywiki.org $:/_tw_shared/sites/talk.tiddlywiki.org $:/_tw_shared/sites/links.tiddlywiki.org $:/_tw_shared/sites/tiddlywiki.com.upgrade $:/_tw_shared/sites/tiddlywiki.com.dev $:/_tw_shared/sites/tiddlywiki.com.prerelease $:/_tw_shared/sites/classic.tiddlywiki.com $:/_tw_shared/sites/marketplace tags: TiddlyWikiSitesMenu diff --git a/editions/tw5.com/tiddlers/about/Archive.tid b/editions/tw5.com/tiddlers/about/Archive.tid new file mode 100644 index 000000000..988f65e7b --- /dev/null +++ b/editions/tw5.com/tiddlers/about/Archive.tid @@ -0,0 +1,82 @@ +title: TiddlyWiki Archive +created: 20231005205623086 +modified: 20231005210538879 +tags: About + +\procedure versions() +5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 +5.1.10 5.1.11 5.1.12 5.1.13 5.1.14 5.1.15 5.1.16 5.1.17 5.1.18 5.1.19 +5.1.20 5.1.21 5.1.22 5.1.23 +5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 +5.3.0 5.3.1 +\end + +Older versions of TiddlyWiki are available in the [[archive|https://github.com/Jermolene/jermolene.github.io/tree/master/archive]]: + +
<$button class="tc-btn-invisible" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}> -<$action-deletefield $field=<>/><$set name="currentTiddlerCSSescaped" value={{{ [escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<>/> +<$action-deletefield $field=<>/> {{$:/core/images/delete-button}}
+ + + + + + + + + <$list filter="[enlistreverse[]]" variable="version"> + <$let + filename=`TiddlyWiki-$(version)$` + emptyFilename=`Empty-$(filename)$` + releaseTiddler={{{ [addprefix[Release ]] }}} + releaseDate={{{ [get[released]format:date[TIMESTAMP]] }}} + nextVersion={{{ [enlistafter] }}} + nextReleaseTiddler={{{ [addprefix[Release ]] }}} + nextReleaseDate={{{ [get[released]format:date[TIMESTAMP]] }}} + lifetime={{{ [subtractdivide[86400000]add[0.5]fixed[0]] }}} + > + + + + + + + + + + +
+ Version + + Released + + Lifetime + + Summary + + Download +
+ <$link to=<>> + <$text text=`v$(version)$`/> + + + <$view tiddler=<> field="released" format="date" template="DDth mmm YYYY"/> + + <$list filter="[compare:number:lt[0]]" variable="ignore"> + Current + + <$list filter="[compare:number:gteq[0]]" variable="ignore"> + <$text text=<>/> + day<$list filter="[!compare:number:eq[1]]" variable="ignore">s + + + <$transclude $tiddler=<> $field="description" $format="inline"> + (none) + + + addprefix[https://tiddlywiki.com/archive/full/]]}}} rel="noopener noreferrer" target="_blank"> + Complete + + | + addprefix[https://tiddlywiki.com/archive/empty/]]}}} rel="noopener noreferrer" target="_blank"> + Empty + +
diff --git a/editions/tw5.com/tiddlers/about/Developers.tid b/editions/tw5.com/tiddlers/about/Developers.tid index 9b24b0c36..51c123ee7 100644 --- a/editions/tw5.com/tiddlers/about/Developers.tid +++ b/editions/tw5.com/tiddlers/about/Developers.tid @@ -8,6 +8,7 @@ There are several resources for developers to learn more about TiddlyWiki and to * [[tiddlywiki.com/dev|https://tiddlywiki.com/dev]] is the official developer documentation * Get involved in the [[development on GitHub|https://github.com/Jermolene/TiddlyWiki5]] +** [img[https://repobeats.axiom.co/api/embed/5a3bb51fd1ebe84a2da5548f78d2d74e456cebf3.svg]] ** [[Discussions|https://github.com/Jermolene/TiddlyWiki5/discussions]] are for Q&A and open-ended discussion ** [[Issues|https://github.com/Jermolene/TiddlyWiki5/issues]] are for raising bug reports and proposing specific, actionable new ideas * The older ~TiddlyWikiDev Google Group is now closed in favour of [[GitHub Discussions|https://github.com/Jermolene/TiddlyWiki5/discussions]] but remains a useful archive: https://groups.google.com/group/TiddlyWikiDev diff --git a/editions/tw5.com/tiddlers/about/Funding TiddlyWiki.tid b/editions/tw5.com/tiddlers/about/Funding TiddlyWiki.tid new file mode 100644 index 000000000..938631d55 --- /dev/null +++ b/editions/tw5.com/tiddlers/about/Funding TiddlyWiki.tid @@ -0,0 +1,19 @@ +title: Funding TiddlyWiki +tags: About HelloThere +modified: 20221204165636777 +created: 20221204165636777 + +TiddlyWiki is more useful to everybody if it is free to use, with no financial barriers to long term adoption. It is not altruism; we believe that removing or reducing barriers to adoption will help to ensure TiddlyWiki's future by making the community larger and stronger. + +Nonetheless, TiddlyWiki is a relatively big, complex machine that requires a significant amount of ongoing work to maintain and improve. Some community infrastructure also requires monthly fees to operate (notably the [[TiddlyWiki forum|Forums]]). + +The people in the community that do the work have widely varying needs: + +* At one end, a good proportion of the work on TiddlyWiki is performed by community members on a purely voluntary basis. For those people, the satisfaction of helping others is sufficient reward. Indeed, for many people, unpaid voluntary activities are a satisfying antidote to everyday paid work +* At the other extreme, JeremyRuston and some other contributors are trying to make a full-time living working on TiddlyWiki by offering commercial products and services around it +* In between, there are other people who would appreciate an ocassional token to reward them for their work + +To support these needs in the community, we have two initiatives: + +* We use [[Open Collective]] to collect donations for the infrastructure costs of the Community and to crowdfund specific developments by individuals or organisations +* The [[TiddlyWiki Marketplace]] provides a shop window for individuals and organisations offering commercial products and services diff --git a/editions/tw5.com/tiddlers/about/Open Collective.tid b/editions/tw5.com/tiddlers/about/Open Collective.tid new file mode 100644 index 000000000..3a98ab274 --- /dev/null +++ b/editions/tw5.com/tiddlers/about/Open Collective.tid @@ -0,0 +1,14 @@ +title: Open Collective +modified: 20221204165636777 +created: 20221204165636777 +tags: About HelloThere + +Open Collective is a platform for transparent fundraising and expenses for projects like TiddlyWiki. It is the official TiddlyWiki community fundraising space. + +https://opencollective.com/tiddlywiki + +You can make a fixed one-time donation, or setup a recurring contribution. + +The main goals listed for donations are to cover basic costs for community infrastructure like the Discourse forum, and a new goal for supporting the TiddlyWiki Core. + +Additionally, the community can make use of the platform for special projects - to pool funds to pay for development, design, or anything else. The [[File Upload Plugin|https://opencollective.com/tiddlywiki/projects/tiddlywiki-file-upload]] is the first of these, and we want to welcome others to launch projects here. diff --git a/editions/tw5.com/tiddlers/commands/CommandsCommand.tid b/editions/tw5.com/tiddlers/commands/CommandsCommand.tid new file mode 100644 index 000000000..84d819a84 --- /dev/null +++ b/editions/tw5.com/tiddlers/commands/CommandsCommand.tid @@ -0,0 +1,8 @@ +created: 20221204202531478 +modified: 20221204202531478 +tags: Commands +title: CommandsCommand +type: text/vnd.tiddlywiki +caption: commands + +{{$:/language/Help/commands}} diff --git a/editions/tw5.com/tiddlers/community/Chinese Community.tid b/editions/tw5.com/tiddlers/community/Chinese Community.tid new file mode 100644 index 000000000..709933b4a --- /dev/null +++ b/editions/tw5.com/tiddlers/community/Chinese Community.tid @@ -0,0 +1,20 @@ +title: 中文社区 - Chinese Community +tags: Community + +# A Chinese community tutorial program that people can edit together: +#* Main site: [ext[https://tw-cn.netlify.app/]] +#* Accelerated access: [ext[https://tw-cn.cpolar.top/]] +#* Alternate: [ext[https://tiddly-wiki-chinese-tutorial.vercel.app]] +# Tiddlywiki Chinese Chat Forum: [ext[https://talk.tidgi.fun/topic/6]] +# Chinese translation of Tiddlywiki official website [ext[https://bramchen.github.io/tw5-docs/zh-Hans/]] +# The best Chinese introductory tutorial for newbies [ext[https://keatonlao.github.io/tiddlywiki-xp/]] + +--- + +# 大家可以一起编辑的中文社区教程项目: +#* 主站:[ext[https://tw-cn.netlify.app/]] +#* 加速访问:[ext[https://tw-cn.cpolar.top/]] +#* 备用:[ext[https://tiddly-wiki-chinese-tutorial.vercel.app]] +# 太微中文交流论坛:[ext[https://talk.tidgi.fun/topic/6]] +# 太微官网汉化版:[ext[https://bramchen.github.io/tw5-docs/zh-Hans/]] +# 最适合新手的中文入门教程:[ext[https://keatonlao.github.io/tiddlywiki-xp/]] diff --git a/editions/tw5.com/tiddlers/community/TiddlyWiki Newsletter.tid b/editions/tw5.com/tiddlers/community/TiddlyWiki Newsletter.tid new file mode 100644 index 000000000..135a34617 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/TiddlyWiki Newsletter.tid @@ -0,0 +1,6 @@ +title: TiddlyWiki Newsletter + +Subscribe to the ~TiddlyWiki Newsletter here: + + + diff --git a/editions/tw5.com/tiddlers/community/editions/Drift by Tony K.tid b/editions/tw5.com/tiddlers/community/editions/Drift by Tony K.tid index 7c4112db7..2f3876929 100644 --- a/editions/tw5.com/tiddlers/community/editions/Drift by Tony K.tid +++ b/editions/tw5.com/tiddlers/community/editions/Drift by Tony K.tid @@ -1,15 +1,16 @@ created: 20210101161529206 -modified: 20210101201435693 +modified: 20230110220010665 tags: [[Community Editions]] title: "Drift - Collect, Organise, Grow." by Tony K -url: https://akhater.github.io/drift/ +type: text/vnd.tiddlywiki +url: https://github.com/bmann/drift-tiddlywiki-template/tree/master/drift A adaptation of TiddlyWiki perfect for using as a Notebook sysetem. {{!!url}} <<< -Drift is an adaptation of TiddlyWiki with the goal of helping you Collect. Organize. and Grow. your ideas while keeping tab on how they interconnect together and fluidly Drift from one to another. +Drift is an adaptation of TiddlyWiki with the goal of helping you Collect. Organise. and Grow. your ideas while keeping tab on how they interconnect together and fluidly Drift from one to another. The 2 main components of Drift are TWCrosslinks and DailyNotes so you never miss an idea diff --git a/editions/tw5.com/tiddlers/community/editions/TiddlyMemo by oflg.tid b/editions/tw5.com/tiddlers/community/editions/TiddlyMemo by oflg.tid deleted file mode 100644 index 25235632e..000000000 --- a/editions/tw5.com/tiddlers/community/editions/TiddlyMemo by oflg.tid +++ /dev/null @@ -1,16 +0,0 @@ -created: 20220417010615742 -modified: 20220417011547812 -tags: [[Community Plugins]] [[Community Editions]] Resources -title: TiddlyMemo by oflg -type: text/vnd.tiddlywiki -url: https://tiddlymemo.org/ - -Lifelong knowledge, deep in the Sea of Mind. - -{{!!url}} - -~TiddlyMemo uses advanced [[Incremental Learning|https://help.supermemo.org/wiki/Incremental_learning]] concepts to make it your powerful second brain for acquiring lifelong knowledge. - -* [[Read Articles|https://tiddlymemo.org/#Read%20Articles]] like ~SuperMemo -* [[Learn languages|https://tiddlymemo.org/#Learn%20languages]] like ~LingQ -* [[Memory Notes|https://tiddlymemo.org/#Memory%20Notes]] like Anki \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/editions/Tidme by oflg.tid b/editions/tw5.com/tiddlers/community/editions/Tidme by oflg.tid new file mode 100644 index 000000000..f32624b50 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/editions/Tidme by oflg.tid @@ -0,0 +1,16 @@ +created: 20220417010615742 +modified: 20231005060241771 +tags: [[Community Editions]] +title: Tidme by oflg +type: text/vnd.tiddlywiki +url: https://github.com/oflg/Tidme + +Lifelong knowledge, deep in Mind. + +{{!!url}} + +Tidme uses advanced [[Incremental Learning|https://help.supermemo.org/wiki/Incremental_learning]] concepts to make it your powerful second brain for acquiring lifelong knowledge. + +* Read Articles like SuperMemo +* Learn languages like LingQ +* Memory Notes like Anki \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/editions/_Noteself_ by Danielo Rodriguez.tid b/editions/tw5.com/tiddlers/community/editions/_Noteself_ by Danielo Rodriguez.tid index 8c088ba9c..6333856d5 100644 --- a/editions/tw5.com/tiddlers/community/editions/_Noteself_ by Danielo Rodriguez.tid +++ b/editions/tw5.com/tiddlers/community/editions/_Noteself_ by Danielo Rodriguez.tid @@ -11,7 +11,7 @@ title: "Noteself" by Danielo Rodríguez type: text/vnd.tiddlywiki url: https://noteself.github.io/ -~NoteSelf is your personal, private, customizable, Evernote-like experience. +~NoteSelf is your personal, private, customisable, Evernote-like experience. You want cloud? Fine! You don't? Fine too! It's all yours, It's your decision! Why not be a bit selfish? @@ -26,9 +26,9 @@ You already know and love Evernote, we know it. It is comfortable, it syncs, has Wow, it's almost perfect, but what about: * Privacy - Everything is stored on the Evernote's servers! -* Customization - If you don't like the interface of Evernote, there's nothing you can do +* Customisation - If you don't like the interface of Evernote, there's nothing you can do -~NoteSelf is built on top of ~TiddlyWiki, a powerful, free, highly customizable and open-source personal wiki. -We took the best of it, it's powerful customization system, and mixed it with one of the best -embedded databases available, [[PouchDb|http://www.pouchdb.com]], for bringing the synchronization capabilities you need. +~NoteSelf is built on top of ~TiddlyWiki, a powerful, free, highly customisable and open-source personal wiki. +We took the best of it, it's powerful customisation system, and mixed it with one of the best +embedded databases available, [[PouchDb|http://www.pouchdb.com]], for bringing the synchronisation capabilities you need. <<< diff --git a/editions/tw5.com/tiddlers/community/examples/A Thesis Notebook.tid b/editions/tw5.com/tiddlers/community/examples/A Thesis Notebook.tid index c43fb1475..0107eeba3 100644 --- a/editions/tw5.com/tiddlers/community/examples/A Thesis Notebook.tid +++ b/editions/tw5.com/tiddlers/community/examples/A Thesis Notebook.tid @@ -11,7 +11,7 @@ A thesis notebook based on TiddlyWiki. <<< This is an example of a thesis notebook powered by TiddlyWiki 5.0.8-beta. -TiddlyWiki is a great piece of software created by Jeremy Ruston. It allows you, among other things, to take notes, organize ideas, store information, and display all your stuff the way you want. It is an incredibly flexible tool you can adapt to fit almost all your needs. +TiddlyWiki is a great piece of software created by Jeremy Ruston. It allows you, among other things, to take notes, organise ideas, store information, and display all your stuff the way you want. It is an incredibly flexible tool you can adapt to fit almost all your needs. This TiddlyWiki has been customized to serve as a philosophy notebook centered around authors, books and papers, concepts and theories, and personal notes. I use it along with Zotero, which is a dedicated bibliography software. Both are free, open source projects. TiddlyWiki can be downloaded at https://tiddlywiki.com. <<< diff --git a/editions/tw5.com/tiddlers/community/plugins/FSRS4TW by oflg.tid b/editions/tw5.com/tiddlers/community/plugins/FSRS4TW by oflg.tid new file mode 100644 index 000000000..b5e19e442 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/plugins/FSRS4TW by oflg.tid @@ -0,0 +1,10 @@ +created: 20220417010615742 +modified: 20231005060241771 +tags: [[Community Plugins]] +title: Free Spaced Repetition Scheduler for TiddlyWiki by oflg +type: text/vnd.tiddlywiki +url: https://github.com/open-spaced-repetition/fsrs4tw + +TiddlyWiki-based memory programme using advanced FSRS algorithm + +{{!!url}} \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/plugins/Plugins by TheDiveO.tid b/editions/tw5.com/tiddlers/community/plugins/Plugins by TheDiveO.tid index e65332804..c81cbbb35 100644 --- a/editions/tw5.com/tiddlers/community/plugins/Plugins by TheDiveO.tid +++ b/editions/tw5.com/tiddlers/community/plugins/Plugins by TheDiveO.tid @@ -12,11 +12,11 @@ A collection of plugins from TheDiveO. [[TheDiveO's Third Flow|http://thediveo.github.io/ThirdFlow/]] plugin construction system: <<< -The ~ThirdFlow plugin brings to you another way to develop customization plugins for TiddlyWiki 5. It is not enforcing a specific development flow, it simply tries to help you. Otherwise, it tries to stay out of your way. +The ~ThirdFlow plugin brings to you another way to develop customisation plugins for TiddlyWiki 5. It is not enforcing a specific development flow, it simply tries to help you. Otherwise, it tries to stay out of your way. <<< [[TheDiveO's FontAwesome|http://thediveo.github.io/TW5FontAwesome/]] plugin: <<< -The FontAwesome plugin supports embedding Font Awesome in TiddlyWiki 5. There is no need to install this font into your operating system in order to use it with TiddlyWiki 5. The font is already embedded in this TiddlyWiki 5 customization plugin instead, so nothing else to install. +The FontAwesome plugin supports embedding Font Awesome in TiddlyWiki 5. There is no need to install this font into your operating system in order to use it with TiddlyWiki 5. The font is already embedded in this TiddlyWiki 5 customisation plugin instead, so nothing else to install. <<< diff --git a/editions/tw5.com/tiddlers/community/plugins/Shiraz by Mohammad.tid b/editions/tw5.com/tiddlers/community/plugins/Shiraz by Mohammad.tid index a8691284d..2f81a10e5 100644 --- a/editions/tw5.com/tiddlers/community/plugins/Shiraz by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/plugins/Shiraz by Mohammad.tid @@ -9,7 +9,7 @@ Shiraz plugin is a very small in size and framework to create stylish contents i {{!!url}} -Shiraz plugin contains extended markups, macros, styles, and many customization to empty Tiddlywiki and can be used as a ''starter kit''. +Shiraz plugin contains extended markups, macros, styles, and many customisation to empty Tiddlywiki and can be used as a ''starter kit''. Some of Shiraz features are: @@ -18,7 +18,7 @@ Some of Shiraz features are: * Sortable tables * Display on demand, slider, and details * Images, basic image macros, slidein, and overlay images, polaroid and pretty images -* Table customization tools +* Table customisation tools * Sticky footer * Multi columns tiddler * Multi column story river diff --git a/editions/tw5.com/tiddlers/community/plugins/TiddlyMap by Felix Kuppers.tid b/editions/tw5.com/tiddlers/community/plugins/TiddlyMap by Felix Kuppers.tid index 9e8cc8283..b111a248b 100644 --- a/editions/tw5.com/tiddlers/community/plugins/TiddlyMap by Felix Kuppers.tid +++ b/editions/tw5.com/tiddlers/community/plugins/TiddlyMap by Felix Kuppers.tid @@ -11,8 +11,8 @@ An interactive network visualisation plugin based on [[Vis.js|http://visjs.org]] ~TiddlyMap is a TiddlyWiki plugin that allows you to link your wiki-topics (tiddlers) in order to create clickable graphs. By creating relations between your topics you can easily do the following: * Create concept maps and quickly manifest your ideas in tiddlers. -* Create task-dependency graphs to organize and describe your tasks. -* Visualize your topic structures to get an immediate grasp of topics and relations. +* Create task-dependency graphs to organise and describe your tasks. +* Visualise your topic structures to get an immediate grasp of topics and relations. -In general you may create, visualize and describe any network-structure you have in mind. +In general you may create, visualise and describe any network-structure you have in mind. <<< diff --git a/editions/tw5.com/tiddlers/community/plugins/TiddlyWiki for Scholars.tid b/editions/tw5.com/tiddlers/community/plugins/TiddlyWiki for Scholars.tid index f53bf3d21..3bdc1c269 100644 --- a/editions/tw5.com/tiddlers/community/plugins/TiddlyWiki for Scholars.tid +++ b/editions/tw5.com/tiddlers/community/plugins/TiddlyWiki for Scholars.tid @@ -10,5 +10,5 @@ An early release of an edition of TiddlyWiki customised for rigorous, academic n {{!!url}} <<< -TiddlyWiki for Scholars is a personal customization of TiddlyWiki 5.0.13-beta I made for note-taking from readings, but it can be useful for other purposes. The idea behind this adaptation is to show and to allow creating relevant data related to the current tiddler without leaving the tiddler. +TiddlyWiki for Scholars is a personal customisation of TiddlyWiki 5.0.13-beta I made for note-taking from readings, but it can be useful for other purposes. The idea behind this adaptation is to show and to allow creating relevant data related to the current tiddler without leaving the tiddler. <<< diff --git a/editions/tw5.com/tiddlers/community/plugins/Tiddlyshow by Mohammad.tid b/editions/tw5.com/tiddlers/community/plugins/Tiddlyshow by Mohammad.tid index a9e588a4b..d7364fce3 100644 --- a/editions/tw5.com/tiddlers/community/plugins/Tiddlyshow by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/plugins/Tiddlyshow by Mohammad.tid @@ -13,4 +13,4 @@ Tiddlyshow contains the following features * Tools for preparing slides * Shortcut keys for navigation (forward and backward) -* Themes to colorify and customize the slideshow +* Themes to colorify and customise the slideshow diff --git a/editions/tw5.com/tiddlers/community/plugins/Todolist by Mohammad.tid b/editions/tw5.com/tiddlers/community/plugins/Todolist by Mohammad.tid index 5d9d9646b..7e395814b 100644 --- a/editions/tw5.com/tiddlers/community/plugins/Todolist by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/plugins/Todolist by Mohammad.tid @@ -9,6 +9,6 @@ Todolist is a small pure wikitext plugin, contain all tools to work with todo l {{!!url}} -With Todolist, easily organize and prioritize your tasks and projects so you’ll always know exactly what to work on next. +With Todolist, easily organise and prioritise your tasks and projects so you’ll always know exactly what to work on next. Todolist creates custom UI and lets you to add new items, set priority, done/undone items, archive, delete. Using Todolist plugin it is possible to create several todo lists in one Tiddlywiki. diff --git a/editions/tw5.com/tiddlers/community/plugins/_JD Mobile Layout plugin_ by JD.tid b/editions/tw5.com/tiddlers/community/plugins/_JD Mobile Layout plugin_ by JD.tid index 6bd891b23..6c1593a09 100644 --- a/editions/tw5.com/tiddlers/community/plugins/_JD Mobile Layout plugin_ by JD.tid +++ b/editions/tw5.com/tiddlers/community/plugins/_JD Mobile Layout plugin_ by JD.tid @@ -1,5 +1,4 @@ created: 20171107181449175 -creator: Ste Willson modified: 20210106151027136 tags: [[Community Plugins]] title: "JD Mobile Layout plugin" by JD diff --git a/editions/tw5.com/tiddlers/community/plugins/_Slides and Stories_ by Jan.tid b/editions/tw5.com/tiddlers/community/plugins/_Slides and Stories_ by Jan.tid index 2a794305d..b8167db1b 100644 --- a/editions/tw5.com/tiddlers/community/plugins/_Slides and Stories_ by Jan.tid +++ b/editions/tw5.com/tiddlers/community/plugins/_Slides and Stories_ by Jan.tid @@ -5,7 +5,7 @@ title: "Slides and Stories" by Jan type: text/vnd.tiddlywiki url: http://slidesnstories.tiddlyspot.com -Slides and Stories is a repository of the tools to optimize TW for scientific research and for presenting and publishing results. +Slides and Stories is a repository of the tools to optimise TW for scientific research and for presenting and publishing results. {{!!url}} diff --git a/editions/tw5.com/tiddlers/community/resources/BrainTest.tid b/editions/tw5.com/tiddlers/community/resources/BrainTest.tid index c278f50ad..db0b2581e 100644 --- a/editions/tw5.com/tiddlers/community/resources/BrainTest.tid +++ b/editions/tw5.com/tiddlers/community/resources/BrainTest.tid @@ -12,5 +12,5 @@ A collection of customisations and macros from Danielo Rodriguez. <<< This is my personal tiddlywiki file for testing. -Here I will post the tools and Macros that I develop for this awesome tool. That way, all the help the comunity gave me can came back to the comunity again. +Here I will post the tools and Macros that I develop for this awesome tool. That way, all the help the community gave me can came back to the community again. <<< diff --git a/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid index 0ade3cbe5..df4df2559 100644 --- a/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid @@ -5,7 +5,7 @@ title: RegExp in Tiddlywiki by Mohammad type: text/vnd.tiddlywiki url: http://tw-regexp.tiddlyspot.com/ -~RegExp in Tiddlywiki contains practical use cases of reular expression in Tiddlywiki. +~RegExp in Tiddlywiki contains practical use cases of regular expression in Tiddlywiki. {{!!url}} diff --git a/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid index a552f8314..d2ff0400e 100644 --- a/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid @@ -5,14 +5,14 @@ title: Semantic Colors by Mohammad type: text/vnd.tiddlywiki url: https://kookma.github.io/TW-Semantic-Colors/ -Semantic colors are set of CSS to apply colorful theme to individual tiddlers for categorization purpose. +Semantic colors are set of CSS to apply colorful theme to individual tiddlers for categorisation purpose. {{!!url}} Tiddlywiki "semantic colors" has two objectives: # How it is simply possible to apply theme to an individual tiddler -# Use semantic colors for categorization +# Use semantic colors for categorisation ;Some use cases :Learning materials (each topic, category can have dedicated semantic color, like learning a foreign language) diff --git a/editions/tw5.com/tiddlers/community/resources/TW5-firebase_ TiddlyWiki5 for Google Firebase by Peter Neumark.tid b/editions/tw5.com/tiddlers/community/resources/TW5-firebase_ TiddlyWiki5 for Google Firebase by Peter Neumark.tid index 0458b4a55..1e1dc2b92 100644 --- a/editions/tw5.com/tiddlers/community/resources/TW5-firebase_ TiddlyWiki5 for Google Firebase by Peter Neumark.tid +++ b/editions/tw5.com/tiddlers/community/resources/TW5-firebase_ TiddlyWiki5 for Google Firebase by Peter Neumark.tid @@ -20,7 +20,7 @@ I've been using TiddlyWiki5 with Google Firebase for over a year now. It's stabl Please consider this version a proof of concept rather than a polished product! My focus was on multi-device or small-team collaboration: -* Basic authorization (bags have an access policy determining who can read / write them). +* Basic authorisation (bags have an access policy determining who can read / write them). * Multiple wikis can be hosted under a single firebase account. * It uses Firebase's built-in social auth to log in users. * Tiddlers are written individually with locking, preventing users overwriting each others' updates. diff --git a/editions/tw5.com/tiddlers/community/resources/TiddlyServer by Arlen Beiler.tid b/editions/tw5.com/tiddlers/community/resources/TiddlyServer by Arlen Beiler.tid index 88c0bf623..9cb1f5272 100644 --- a/editions/tw5.com/tiddlers/community/resources/TiddlyServer by Arlen Beiler.tid +++ b/editions/tw5.com/tiddlers/community/resources/TiddlyServer by Arlen Beiler.tid @@ -18,7 +18,7 @@ An extension to the Node.js configuration of TiddlyWiki that adds support for st <<< TiddlyServer 2.0 takes the server command of TiddlyWiki on NodeJS and adds it to a static file server. This means you can load and serve any TiddlyWiki data folder in the same way you can serve a single file TiddlyWiki. -But you don't need to serve files and folders from just one place, you can serve them from multiple places anywhere on your harddrive (literally anywhere NodeJS can stat, readdir, and readFile). You can even organize them into virtual folders (aka aliases in Apache and mounts in Express). +But you don't need to serve files and folders from just one place, you can serve them from multiple places anywhere on your harddrive (literally anywhere NodeJS can stat, readdir, and readFile). You can even organise them into virtual folders (aka aliases in Apache and mounts in Express). The main point, of course, is that you can actually edit your files, not just look at them. Single file TiddlyWikis use the put saver, which needs to be patched using a bookmarklet included on the index page. The instructions for this are below under the heading "One thing that needs to be noted". diff --git a/editions/tw5.com/tiddlers/community/resources/TiddlyWiki Posts.tid b/editions/tw5.com/tiddlers/community/resources/TiddlyWiki Posts.tid index 0c3d37cff..c9cbb7e96 100644 --- a/editions/tw5.com/tiddlers/community/resources/TiddlyWiki Posts.tid +++ b/editions/tw5.com/tiddlers/community/resources/TiddlyWiki Posts.tid @@ -1,11 +1,11 @@ created: 20140129085406905 -modified: 20210106151027268 +modified: 20230805140720289 tags: [[Other Resources]] Articles title: "TiddlyWiki Posts" by Jeffrey Kishner type: text/vnd.tiddlywiki -url: http://blog.jeffreykishner.com/tiddlywiki/ +url: https://web.archive.org/web/20221015011644/http://blog.jeffreykishner.com/tiddlywiki/ -A collection of articles covering integration with Fargo, Font Awesome and Google Calendar, and tips for managing task lists. +A collection of articles covering integration with Fargo, Font Awesome and Google Calendar, and tips for managing task lists. The original site is missing, but a link to an archive is provided. {{!!url}} diff --git a/editions/tw5.com/tiddlers/community/resources/_Dropboard_ by Reid Gould.tid b/editions/tw5.com/tiddlers/community/resources/_Dropboard_ by Reid Gould.tid index 6f0eb3523..5c528b083 100644 --- a/editions/tw5.com/tiddlers/community/resources/_Dropboard_ by Reid Gould.tid +++ b/editions/tw5.com/tiddlers/community/resources/_Dropboard_ by Reid Gould.tid @@ -1,12 +1,11 @@ created: 20171111192738730 -creator: MAS modified: 20210106151027013 tags: [[Other Resources]] title: "Dropboard" by Reid Gould type: text/vnd.tiddlywiki url: https://github.com/reidgould/tiddlywiki-dropboard -A TiddlyWiki plugin for kanban-like organization in the style of Trello™ using boards, lists, and cards. +A TiddlyWiki plugin for kanban-like organisation in the style of Trello™ using boards, lists, and cards. {{!!url}} diff --git a/editions/tw5.com/tiddlers/community/resources/_Hacks_ by Thomas Elmiger.tid b/editions/tw5.com/tiddlers/community/resources/_Hacks_ by Thomas Elmiger.tid index 8d9cb326b..dac485c6c 100644 --- a/editions/tw5.com/tiddlers/community/resources/_Hacks_ by Thomas Elmiger.tid +++ b/editions/tw5.com/tiddlers/community/resources/_Hacks_ by Thomas Elmiger.tid @@ -1,7 +1,5 @@ created: 20161226165024380 -creator: Thomas Elmiger modified: 20210106151027097 -modifier: Thomas Elmiger tags: [[Other Resources]] title: "Hacks" by Thomas Elmiger type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/_MathCell_ by Ste Wilson.tid b/editions/tw5.com/tiddlers/community/resources/_MathCell_ by Ste Wilson.tid index 20957e433..d804f9052 100644 --- a/editions/tw5.com/tiddlers/community/resources/_MathCell_ by Ste Wilson.tid +++ b/editions/tw5.com/tiddlers/community/resources/_MathCell_ by Ste Wilson.tid @@ -1,5 +1,4 @@ created: 20161226165024380 -creator: Ste Willson modified: 20210106151027156 tags: [[Other Resources]] title: "MathCell" by Stephen Kimmel diff --git a/editions/tw5.com/tiddlers/community/resources/_TiddlyServer_ by Matt Lauber.tid b/editions/tw5.com/tiddlers/community/resources/_TiddlyServer_ by Matt Lauber.tid index 4b1e660c2..6a65fe825 100644 --- a/editions/tw5.com/tiddlers/community/resources/_TiddlyServer_ by Matt Lauber.tid +++ b/editions/tw5.com/tiddlers/community/resources/_TiddlyServer_ by Matt Lauber.tid @@ -1,5 +1,4 @@ created: 20161226165024380 -creator: Matt Lauber modified: 20211113230709926 tags: [[Other Resources]] title: "TiddlyServer" by Matt Lauber diff --git a/editions/tw5.com/tiddlers/community/resources/_Timimi_ Extension and executable by Riz.tid b/editions/tw5.com/tiddlers/community/resources/_Timimi_ Extension and executable by Riz.tid index 475de4308..71045853c 100644 --- a/editions/tw5.com/tiddlers/community/resources/_Timimi_ Extension and executable by Riz.tid +++ b/editions/tw5.com/tiddlers/community/resources/_Timimi_ Extension and executable by Riz.tid @@ -13,6 +13,8 @@ url: https://ibnishak.github.io/Timimi/ Timimi is a web-extension accompanied by a native host that allows you to save and backup your standalone HTML tiddlywiki files ''anywhere in your hard-drive''. Once installed, you can save the tiddlywiki files without any extra steps, like the original Tiddlyfox addon. +* The native host requires a component installed on the host computer, outside the browser. + {{!!url}} As of version 2.1, Timimi supports the following browsers @@ -29,4 +31,4 @@ Timimi also provides users with 4 backup strategies, viz: * Create a backup Every n^^th^^ save * Create a backup every n^^th^^ minute * Customised Tower of Hanoi -* First in First Out \ No newline at end of file +* First in First Out diff --git a/editions/tw5.com/tiddlers/community/resources/_X3DOM for TiddlyWiki 5_ by Jamal Wills.tid b/editions/tw5.com/tiddlers/community/resources/_X3DOM for TiddlyWiki 5_ by Jamal Wills.tid index 4df710ad4..c7e2790e2 100644 --- a/editions/tw5.com/tiddlers/community/resources/_X3DOM for TiddlyWiki 5_ by Jamal Wills.tid +++ b/editions/tw5.com/tiddlers/community/resources/_X3DOM for TiddlyWiki 5_ by Jamal Wills.tid @@ -1,5 +1,4 @@ created: 20171107175718679 -creator: Ste Willson modified: 20210106151027400 tags: [[Other Resources]] title: "X3DOM for TiddlyWiki 5" by Jamal Wills diff --git a/editions/tw5.com/tiddlers/community/resources/_file-backups_ Extension Firefox by pmario.tid b/editions/tw5.com/tiddlers/community/resources/_file-backups_ Extension Firefox by pmario.tid index e023a34d9..aa111108e 100644 --- a/editions/tw5.com/tiddlers/community/resources/_file-backups_ Extension Firefox by pmario.tid +++ b/editions/tw5.com/tiddlers/community/resources/_file-backups_ Extension Firefox by pmario.tid @@ -11,7 +11,7 @@ title: "file-backups" Extension for Firefox by pmario type: text/vnd.tiddlywiki url: https://github.com/pmario/file-backups -An extension for Mozilla Firefox that smoothes out some of the friction from ~TiddlyWiki's built-in [[HTML5 fallback saver|Saving with the HTML5 fallback saver]], making it almost as easy to use as ~TiddlyFox. The workflow is intended to work out of the box, without configuration. +An extension for Mozilla Firefox that smoothes out some of the friction from ~TiddlyWiki's built-in [[HTML5 saver|Saving with the HTML5 saver]], making it almost as easy to use as ~TiddlyFox. The workflow is intended to work out of the box, without configuration. https://github.com/pmario/file-backups which contains links to the documentation and introduction video(s). diff --git a/editions/tw5.com/tiddlers/community/resources/_savetiddlers_ Extension for Chrome and Firefox by buggyj.tid b/editions/tw5.com/tiddlers/community/resources/_savetiddlers_ Extension for Chrome and Firefox by buggyj.tid index 1eaa83302..f000b92c9 100644 --- a/editions/tw5.com/tiddlers/community/resources/_savetiddlers_ Extension for Chrome and Firefox by buggyj.tid +++ b/editions/tw5.com/tiddlers/community/resources/_savetiddlers_ Extension for Chrome and Firefox by buggyj.tid @@ -11,6 +11,6 @@ title: "savetiddlers" Extension for Chrome and Firefox by buggyj type: text/vnd.tiddlywiki url: https://github.com/buggyj/savetiddlers -An extension for Google Chrome and Mozilla Firefox that smoothes out some of the friction from TiddlyWiki's built-in [[HTML5 fallback saver|Saving with the HTML5 fallback saver]], making it almost as easy to use as TiddlyFox once it is set up correctly. +An extension for Google Chrome and Mozilla Firefox that smoothes out some of the friction from TiddlyWiki's built-in [[HTML5 saver|Saving with the HTML5 saver]], making it almost as easy to use as TiddlyFox once it is set up correctly. https://github.com/buggyj/savetiddlers diff --git a/editions/tw5.com/tiddlers/community/themes/Notebook theme by Nicolas Petton.tid b/editions/tw5.com/tiddlers/community/themes/Notebook theme by Nicolas Petton.tid index c31316239..4f86181d3 100644 --- a/editions/tw5.com/tiddlers/community/themes/Notebook theme by Nicolas Petton.tid +++ b/editions/tw5.com/tiddlers/community/themes/Notebook theme by Nicolas Petton.tid @@ -1,9 +1,9 @@ created: 20210101154635213 -modified: 20210110210929321 +modified: 20240131143350890 tags: [[Community Themes]] title: "Notebook theme" by Nicolas Petton type: text/vnd.tiddlywiki -url: https://nicolas.petton.fr/tw/notebook.html +url: https://saqimtiaz.github.io/sq-tw/notebook.html Notebook is a clean, uncluttered theme for ~TiddlyWiki. diff --git a/editions/tw5.com/tiddlers/community/tutorials/GitHub Saver Tutorial by Mohammad.tid b/editions/tw5.com/tiddlers/community/tutorials/GitHub Saver Tutorial by Mohammad.tid index 4f4e39c4e..a9063d996 100644 --- a/editions/tw5.com/tiddlers/community/tutorials/GitHub Saver Tutorial by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/tutorials/GitHub Saver Tutorial by Mohammad.tid @@ -1,11 +1,11 @@ created: 20201117163027900 -modified: 20210106151027459 +modified: 20230723074506632 tags: Tutorials title: GitHub Saver Tutorial by Mohammad type: text/vnd.tiddlywiki url: https://kookma.github.io/TW5-GitHub-Saver/ -GitHub Saver is a step by step tutorial shows how to integrate Tiddlywiki 5 and GitHub Pages to create websites hosted on https://github.com/. +GitHub Saver is a step by step tutorial that shows how to integrate Tiddlywiki 5 and ~GitHub Pages to create websites hosted on https://github.com/. {{!!url}} @@ -13,11 +13,11 @@ This instruction is based on Tiddlywiki single html file model, while it can use !! Other tutorials -;Tiddlywiki, Travis-CI and GitHub Pages +;Tiddlywiki, Travis-CI and ~GitHub Pages :https://kookma.github.io/Tiddlywiki-Travis-CI/ :This wiki shows how to set up websites hosted on [[GitHub Pages|https://pages.github.com/]] using [[Travis-CI|https://travis-ci.org]] and [[Tiddlywiki 5|https://tiddlywiki.com]] on Node.js. -;Tiddlywiki and GitHub Pages +;Tiddlywiki and ~GitHub Pages :https://kookma.github.io/Tiddlywiki-and-GitHub-Pages/ -:This instruction is based on local edit, save and push to GitHub. It does NOT use the new GitHub Saver mechanism (requires TW 5.1.20+) which lets edit and save directly from Tiddlywiki! \ No newline at end of file +:This instruction is based on local edit, save and push to ~GitHub. It does NOT use the new ~GitHub Saver mechanism (requires TW 5.1.20+) which lets edit and save directly from Tiddlywiki! \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/tutorials/Install and run TiddlyWiki on a CentOS 6 VPS using Nginx.tid b/editions/tw5.com/tiddlers/community/tutorials/Install and run TiddlyWiki on a CentOS 6 VPS using Nginx.tid deleted file mode 100644 index 4d3895a4d..000000000 --- a/editions/tw5.com/tiddlers/community/tutorials/Install and run TiddlyWiki on a CentOS 6 VPS using Nginx.tid +++ /dev/null @@ -1,16 +0,0 @@ -created: 20140312085406905 -modified: 20140312084543862 -tags: Tutorials -title: "Install and run TiddlyWiki on a CentOS 6 VPS using Nginx" from RoseHosting -type: text/vnd.tiddlywiki -url: http://www.rosehosting.com/blog/install-and-run-tiddlywiki-on-a-centoos-6-vps-using-nginx/ - -A step by step guide to running TiddlyWiki on a ~CentOS Virtual Private Server. - -{{!!url}} - -<<< -In this tutorial we will guide you through the steps of installing and running TiddlyWiki on a ~CentOS 6 VPS. - -We will also install and configure Nginx as a reverse proxy, so you can run TiddlyWiki behind Nginx. -<<< diff --git a/editions/tw5.com/tiddlers/Brackets.tid b/editions/tw5.com/tiddlers/concepts/Brackets.tid similarity index 92% rename from editions/tw5.com/tiddlers/Brackets.tid rename to editions/tw5.com/tiddlers/concepts/Brackets.tid index 529adb17e..fee36313c 100644 --- a/editions/tw5.com/tiddlers/Brackets.tid +++ b/editions/tw5.com/tiddlers/concepts/Brackets.tid @@ -10,5 +10,5 @@ WikiText syntax uses a number of different types of brackets. Their names are sh |`()` |Round brackets |Parenthesis |Not used in WikiText | |`[]` |Square brackets |Brackets |[[Links|Linking in WikiText]], [[Filters|Filters]] | |`{}` |Curly brackets |Braces |[[Text references|TextReference]], [[Filtered attributes|HTML in WikiText]] | -|`<>` |Angle brackets |Chevrons |[[HTML elements and widgets|HTML in WikiText]], [[Macros|Macros in WikiText]] | +|`<>` |Angle brackets |Chevrons |[[HTML elements and widgets|HTML in WikiText]], [[Macros]] | diff --git a/editions/tw5.com/tiddlers/concepts/CoordinateSystems.tid b/editions/tw5.com/tiddlers/concepts/CoordinateSystems.tid new file mode 100644 index 000000000..53c6c4ca9 --- /dev/null +++ b/editions/tw5.com/tiddlers/concepts/CoordinateSystems.tid @@ -0,0 +1,42 @@ +created: 20220810201659784 +modified: 20220810201659784 +tags: Concepts +title: Coordinate Systems +type: text/vnd.tiddlywiki + +TiddlyWiki (primarily the RevealWidget) supports two coordinate systems for positioning popups (see PopupMechanism to learn more about popups). + +<<.from-version "5.2.4">> We introduced absolute coordinates that may not work with all extensions and plugins. For maximum backwards compatibility, use absolute coordinates only where necessary. + +!! Relative coordinate system + +The default coordinate system is relative to the nearest positioned ancestor element. This is either: + +* an element with a non-static position, or +* a ''td'', ''th'', ''table'' in case the element itself is static positioned. + +For tiddlers the nearest positioned ancestor element mostly is the body of the tiddler. Read the next chapter to learn about the exceptions. + +Relative coordinates are expressed in the form ''(x,y,w,h)''. Where ''x'' and ''y'' represent the position and ''w'' and ''h'' the width and height of the element. + +!! Absolute coordinate system + +The relative coordinate system works flawless most of the time. Problems occure if the target element (for example, a popup) and the source element (the triggering button) do not share the same positioned ancestor element. This is often the case if the popup is declared outside a table and the triggering button is declared within a table cell. In this case the coordinate systems have different origins and the popup will be displayed in the wrong location. + +Absolute coordinates can fix this problem by using the root element of the page (the upper-left corner of the page) as the origin of the coordinate system. Absolute coordinates are expressed in the form ''@(x,y,w,h)''. Where ''x'' and ''y'' represent the position and ''w'' and ''h'' the width and height of the element. The leading ''@''-symbol marks these coordinates as absolute. + +The ButtonWidget has an option (''popupAbsCoords'') to put absolute coordinates into the state tiddler. The DraggableWidget and the EventCatcherWidget provide the absolute coordinate of an event within the attribute `tv-popup-abs-coords`. + + +!! Example + +The following example shows a popup that is triggered from within a table cell. The table cell is the nearest positioned ancestor element. The popup was defined outside the table cell. The button using relative coordinates will open the popup in the wrong location because the button and the popup do not agree on the same coordinate system. Using absolute coordinates fixes this problem. + +< +
+Popup +
+ + +| Table Row 1 |<$button popup="$:/state/CoordinateSampleReveal">Relative coordinates| +| Table Row 2 |<$button popup="$:/state/CoordinateSampleReveal" popupAbsCoords="yes">Absolute coordinates|'>> diff --git a/editions/tw5.com/tiddlers/concepts/Date Fields.tid b/editions/tw5.com/tiddlers/concepts/Date Fields.tid index 7ffb40c5c..c58398d19 100644 --- a/editions/tw5.com/tiddlers/concepts/Date Fields.tid +++ b/editions/tw5.com/tiddlers/concepts/Date Fields.tid @@ -1,5 +1,5 @@ created: 20150117190213631 -modified: 20201201154211507 +modified: 20230226144641763 tags: Concepts title: Date Fields type: text/vnd.tiddlywiki @@ -21,6 +21,8 @@ Values of date fields are 17 or 18-character strings: To avoid problems arising from differences of time zone, TiddlyWiki always uses [[UTC|https://en.wikipedia.org/wiki/Coordinated_Universal_Time]]. +The [[DateFormat]] template for storage of dates in these fields is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. + As an example, the <<.field created>> field of this tiddler has the value <<.value """<$view field="created"/>""">>. Dates can be [[converted to other formats|DateFormat]] for display: diff --git a/editions/tw5.com/tiddlers/concepts/Edit Template Body Cascade.tid b/editions/tw5.com/tiddlers/concepts/Edit Template Body Cascade.tid index 25b2553a4..141138283 100644 --- a/editions/tw5.com/tiddlers/concepts/Edit Template Body Cascade.tid +++ b/editions/tw5.com/tiddlers/concepts/Edit Template Body Cascade.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki The edit template body cascade is a [[cascade|Cascades]] used by the default edit template to choose the template for displaying the tiddler body. +The core edit template body cascade can be found in $:/core/ui/EditTemplate/body + The default edit template body cascade consists of: # If the tiddler has the field ''_canonical_uri'' then use the template $:/core/ui/EditTemplate/body/canonical-uri to display the remote URL @@ -13,4 +15,4 @@ The default edit template body cascade consists of: You can see the current settings for the view template body cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Edit Template Body'' tab. -<> \ No newline at end of file +<> diff --git a/editions/tw5.com/tiddlers/concepts/Field Editor Cascade.tid b/editions/tw5.com/tiddlers/concepts/Field Editor Cascade.tid index 2211786e8..114a2fb05 100644 --- a/editions/tw5.com/tiddlers/concepts/Field Editor Cascade.tid +++ b/editions/tw5.com/tiddlers/concepts/Field Editor Cascade.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki The field editor cascade is a [[cascade|Cascades]] used to choose a template for rendering the field editor within the [[EditTemplate|$:/core/ui/EditTemplate/fields]]. +The core field editor cascade can be found in $:/core/ui/EditTemplate/fields + The default field editor cascade only contains one element: # Use the tiddler $:/core/ui/EditTemplate/fieldEditor/default to render the field @@ -14,4 +16,4 @@ See [[Customizing EditTemplate field rendering]] for more details. You can see the current settings for the field editor cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Field Editor'' tab. -<> \ No newline at end of file +<> diff --git a/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid b/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid index caffd063c..1a5a77d17 100644 --- a/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid +++ b/editions/tw5.com/tiddlers/concepts/JSONTiddlers.tid @@ -8,4 +8,4 @@ A JSON tiddler is a [[data tiddler|DataTiddlers]] containing a [[JSON|JavaScript Its [[ContentType]] is `application/json`. -The [[history list|$:/HistoryList]] is an of a JSON tiddler. +The [[history list|$:/HistoryList]] is an example of a JSON tiddler. diff --git a/editions/tw5.com/tiddlers/concepts/Macros.tid b/editions/tw5.com/tiddlers/concepts/Macros.tid index 1d06f9755..884551996 100644 --- a/editions/tw5.com/tiddlers/concepts/Macros.tid +++ b/editions/tw5.com/tiddlers/concepts/Macros.tid @@ -1,31 +1,46 @@ created: 20140211171341271 -modified: 20220505082754270 +modified: 20230922094937115 tags: Concepts Reference title: Macros type: text/vnd.tiddlywiki -A <<.def macro>> is a named snippet of text. WikiText can use the name as a shorthand way of [[transcluding|Transclusion]] the snippet. Such transclusions are known as <<.def "macro calls">>, and each call can supply a different set of parameters that get substituted for special placeholders within the snippet. +!! Important -For the syntax, see [[Macros in WikiText]]. +<<.from-version "5.3.0">> Macros have been [[superseded|Macro Pitfalls]] by [[Procedures]], [[Functions]] and [[Custom Widgets]] which together provide more robust and flexible ways to encapsulate and re-use code. -Most macros are in fact just parameterised [[variables|Variables]]. +For text substitutions it is now recommended to use: [[Substituted Attribute Values]], [[substitute Operator]] and [[Transclusion and Substitution]] -They are created using the `\define` [[pragma|Pragma]]. (Behind the scenes, this is transformed into a <<.wlink SetWidget>>, i.e. macros and variables are two sides of the same coin.) +!! Introduction -The snippet and its incoming parameter values are treated as simple strings of characters with no WikiText meaning, at least until the placeholders have been filled in and the macro call has returned. This means that a macro can assemble and return the complete syntax of a ~WikiText component, such as a [[link|Linking in WikiText]]. (See [[Transclusion and Substitution]] for further discussion of this.) +A <<.def macro>> is a named snippet of text. They are typically defined with the [[Pragma: \define]]: -Within a snippet itself, the only markup detected is `$name$` (a placeholder for a macro parameter) and `$(name)$` (a placeholder for a [[variable|Variables]]). +``` +\define my-macro(parameter:"Default value") +This is the macro, and the parameter is $parameter$. +\end +``` -The <<.mlink dumpvariables>> macro lists all variables (including macros) that are available at that position in the widget tree. +The name wrapped in double angled [[brackets|Brackets]] is used a shorthand way of [[transcluding|Transclusion]] the snippet. Such transclusions are known as <<.def "macro calls">>, and each call can supply a different set of parameters: -An <<.wlink ImportVariablesWidget>> widget can be used to copy macro definitions to another branch of the [[widget tree|Widgets]]. ~TiddlyWiki uses this technique internally to implement global macros -- namely any macros defined in tiddlers with the <<.tag $:/tags/Macro>> tag. +``` +<> +<> +``` -The tag <<.tag $:/tags/Macro/View>> is used to define macros that should only be available within the main view template and the preview panel. +The parameters that are specified in the macro call are substituted for special placeholders within the snippet: -The tag <<.tag $:/tags/Macro/View/Body>> is used to define macros that should only be available within the main view template body and the preview panel. +* `$parameter-name$` is replaced with the value of the named parameter +* `$(variable-name)$` is replaced with the value of the named [[variable|Variables]]). -For maximum flexibility, macros can also be <<.js-macro-link "written as JavaScript modules">>. +!! How Macros Work -A similar effect to a parameterised macro call can be produced by setting [[variables|Variables]] around a [[transclusion|Transclusion]]. +Macros are implemented as a special kind of [[variable|Variables]]. The only thing that distinguishes them from ordinary variables is the way that the parameters are handled. + +!! Using Macros + +* [[Macro Definitions]] describes how to create macros +* [[Macro Calls]] describes how to use macros +* [[Macro Parameter Handling]] describes how macro parameters work +* [[Macro Pitfalls]] describes some of the pitfalls of using macros +* [[Core Macros]] lists the built-in core macros -~TiddlyWiki's core has [[several macros|Core Macros]] built in. diff --git a/editions/tw5.com/tiddlers/concepts/Pragma.tid b/editions/tw5.com/tiddlers/concepts/Pragma.tid index 05a29a2cc..868cf9667 100644 --- a/editions/tw5.com/tiddlers/concepts/Pragma.tid +++ b/editions/tw5.com/tiddlers/concepts/Pragma.tid @@ -1,20 +1,8 @@ + created: 20150219175930000 modified: 20220122182842041 -tags: Concepts [[WikiText Parser Modes]] +tags: title: Pragma type: text/vnd.tiddlywiki -A <<.def pragma>> is a special component of WikiText that provides control over the way the remaining text is parsed. - -Pragmas occupy lines that start with `\`. They can only appear at the start of the text, but blank lines are allowed between them. If a pragma line appears in the main body of the text, it is treated as if it was ordinary text. - -The following pragmas are available: - -;`\define` -: for defining a [[macro|Macros]] -;`\rules` -: for adjusting the set of rules used to parse the text -;`\whitespace trim` or `\whitespace notrim` -: <<.from-version "5.1.15">> Control whether whitespace is trimmed from the start and end of text runs (the default is ''notrim''). This setting can be useful when the whitespace generated by linebreaks disturbs formatting -;`\import ` -: <<.from-version "5.1.18">> for importing macro definitions from tiddlers identified by a filter expression +See [[Pragmas]]. diff --git a/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid b/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid index 11abdd2e9..89417bc65 100644 --- a/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid +++ b/editions/tw5.com/tiddlers/concepts/ShadowTiddlers.tid @@ -9,9 +9,13 @@ tags: Concepts <$button actions=<>>$text$ \end -ShadowTiddlers are tiddlers that are loaded from within [[Plugins]]. Unlike ordinary tiddlers, they don't appear in most lists. +ShadowTiddlers are tiddlers that are loaded from [[Plugins]] at the wiki startup. Unlike ordinary tiddlers, they don't appear in most lists. -ShadowTiddlers can be overridden with an ordinary tiddler of the same name. If that tiddler is subsequently deleted then the original shadow tiddler is automatically restored. +!! Overriding Shadow Tiddlers to modify plugins + +A ShadowTiddler can be overridden with an ordinary tiddler of the same name. This leaves the shadow tiddler intact but the plugin will use the overriding tiddler in its place, effectively allowing users to modify the behaviour of plugins. + +Users are cautioned against overriding shadow tiddlers because if the shadow tiddler is changed in a plugin update, the overriding tiddler may no longer perform as intended. To remedy this, the overriding tiddler may be modified or deleted. If the overriding tiddler is deleted, then the plugin falls back to using the original shadow tiddler. !! Overridden Shadow Tiddlers diff --git a/editions/tw5.com/tiddlers/concepts/Story Tiddler Template.tid b/editions/tw5.com/tiddlers/concepts/Story Tiddler Template.tid index 448079454..50ef0d87c 100644 --- a/editions/tw5.com/tiddlers/concepts/Story Tiddler Template.tid +++ b/editions/tw5.com/tiddlers/concepts/Story Tiddler Template.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki "Story tiddler template" refers to the template used to display a tiddler within the story river. +The core story tiddler template can be found in $:/core/ui/StoryTiddlerTemplate + The [[Story Tiddler Template Cascade]] is used to choose the template to be used for a particular tiddler. By default, the edit template is used for tiddlers in draft mode, and the view template used otherwise. See also: diff --git a/editions/tw5.com/tiddlers/concepts/Tiddler Colour Cascade.tid b/editions/tw5.com/tiddlers/concepts/Tiddler Colour Cascade.tid index 1a290938e..8ec685929 100644 --- a/editions/tw5.com/tiddlers/concepts/Tiddler Colour Cascade.tid +++ b/editions/tw5.com/tiddlers/concepts/Tiddler Colour Cascade.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki The tiddler colour cascade is a [[cascade|Cascades]] used to choose which colour should be used for a particular tiddler. +Core tiddler colour cascades can be found in $:/core/macros/tag, $:/core/ui/Components/tag-link, $:/core/ui/EditTemplate/tags, $:/core/ui/TagPickerTagTemplate, $:/core/ui/TagTemplate and $:/core/ui/ViewTemplate/title + The default tiddler colour cascade consists of: # If the tiddler has a ''color'' field, use the value as the colour @@ -13,4 +15,4 @@ The default tiddler colour cascade consists of: You can see the current settings for the tiddler colour cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Colour'' tab. -<> \ No newline at end of file +<> diff --git a/editions/tw5.com/tiddlers/concepts/Tiddler Icon Cascade.tid b/editions/tw5.com/tiddlers/concepts/Tiddler Icon Cascade.tid index 01af98e1a..4eef508c1 100644 --- a/editions/tw5.com/tiddlers/concepts/Tiddler Icon Cascade.tid +++ b/editions/tw5.com/tiddlers/concepts/Tiddler Icon Cascade.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki The tiddler icon cascade is a [[cascade|Cascades]] used to choose which icon should be used for a particular tiddler. +The core tiddler icon cascade can be found in $:/core/ui/TiddlerIcon + The default tiddler icon cascade consists of: # If the tiddler has an ''icon'' field, use the value as the title of the icon tiddler @@ -13,4 +15,4 @@ The default tiddler icon cascade consists of: You can see the current settings for the tiddler icon cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''Tiddler Icon'' tab. -<> \ No newline at end of file +<> diff --git a/editions/tw5.com/tiddlers/concepts/TiddlerFields.tid b/editions/tw5.com/tiddlers/concepts/TiddlerFields.tid index 0f9b830a7..22017c570 100644 --- a/editions/tw5.com/tiddlers/concepts/TiddlerFields.tid +++ b/editions/tw5.com/tiddlers/concepts/TiddlerFields.tid @@ -24,7 +24,7 @@ The standard fields are: Other fields used by the core are: |!Field Name |!Description | -|`class` |<> | +|`class` |<<.from-version "5.1.16">> <> | |`code-body` |<<.from-version "5.2.1">> <> | |`color` |<> | |`description` |<> | diff --git a/editions/tw5.com/tiddlers/concepts/Title List.tid b/editions/tw5.com/tiddlers/concepts/Title List.tid index a49a665ad..67bb4e339 100644 --- a/editions/tw5.com/tiddlers/concepts/Title List.tid +++ b/editions/tw5.com/tiddlers/concepts/Title List.tid @@ -1,5 +1,5 @@ created: 20150117152418000 -modified: 20220523075540462 +modified: 20231019155036098 tags: Concepts title: Title List type: text/vnd.tiddlywiki @@ -15,3 +15,7 @@ Title lists are used in various places, including PermaLinks and the ListField. They are in fact the simplest case of a [[filter|Filters]], and are thus a way of expressing a [[selection of titles|Title Selection]]. <<.warning """The [[Title List]] format cannot reliably represent items that contain certain specific character sequences such as `]] `. Thus it should not be used where there is a possibility of such sequences occurring.""">> + +See also: + +* The [[format Operator]] with the 'titlelist' suffix conditionally wraps double square brackets around a string if it contains whitespace diff --git a/editions/tw5.com/tiddlers/concepts/View Template Title Cascade.tid b/editions/tw5.com/tiddlers/concepts/View Template Title Cascade.tid index ef3a29c48..cac8f5ac5 100644 --- a/editions/tw5.com/tiddlers/concepts/View Template Title Cascade.tid +++ b/editions/tw5.com/tiddlers/concepts/View Template Title Cascade.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki The view template title cascade is a [[cascade|Cascades]] used by the default view template to choose the template for displaying the tiddler title. +The core view template title cascade can be found in $:/core/ui/ViewTemplate/title + The default view template title cascade consists of: # If the tiddler title starts with `$:/` then use the template $:/core/ui/ViewTemplate/title/system which causes the `$:/` prefix to be displayed in pale text @@ -13,4 +15,4 @@ The default view template title cascade consists of: You can see the current settings for the view template title cascade in $:/ControlPanel under the ''Info'' -> ''Advanced'' -> ''Cascades'' -> ''View Template Title'' tab. -<> \ No newline at end of file +<> diff --git a/editions/tw5.com/tiddlers/concepts/Wiki.tid b/editions/tw5.com/tiddlers/concepts/Wiki.tid index f1bd49505..107dc6a4c 100644 --- a/editions/tw5.com/tiddlers/concepts/Wiki.tid +++ b/editions/tw5.com/tiddlers/concepts/Wiki.tid @@ -3,4 +3,4 @@ tags: Concepts Groups of uniquely titled tiddlers are contained in WikiStore objects. -The WikiStore also manages the plugin modules used for widgets, and operations like serializing, deserializing, parsing and rendering tiddlers. +The WikiStore also manages the plugin modules used for widgets, and operations like serialising, deserialising, parsing and rendering tiddlers. diff --git a/editions/tw5.com/tiddlers/concepts/WikiText.tid b/editions/tw5.com/tiddlers/concepts/WikiText.tid index 6c4ab0b3a..c8d0141bc 100644 --- a/editions/tw5.com/tiddlers/concepts/WikiText.tid +++ b/editions/tw5.com/tiddlers/concepts/WikiText.tid @@ -1,15 +1,15 @@ created: 20131205155227468 -modified: 20140919191220377 +modified: 20230303214711802 tags: Concepts Reference title: WikiText type: text/vnd.tiddlywiki -~WikiText is a concise, expressive way of typing a wide range of text formatting, hypertext and interactive features. It allows you to focus on writing without a complex user interface getting in the way. It is designed to be familiar for users of [[MarkDown|http://daringfireball.net/projects/markdown/]], but with more of a focus on linking and the interactive features. +~WikiText is a concise, expressive way of typing a wide range of text formatting, hypertext and interactive features. It allows you to focus on writing without a complex user interface getting in the way. It is designed to be familiar for users of [[Markdown]] but with more of a focus on linking and the interactive features. -~WikiText can also be inserted to the text field using the [[Editor toolbar]]. +~WikiText can also be inserted to the text field using the [[Editor toolbar]] buttons. -See [[Formatting text in TiddlyWiki]] for an introduction to WikiText. +See [[Formatting in WikiText]] and [[Formatting text in TiddlyWiki]] for an introduction to ~WikiText. -The following elements of WikiText syntax are built into the core: +The following elements of ~WikiText syntax are built into the core: -<> +<> diff --git a/editions/tw5.com/tiddlers/customising/Customising TiddlyWiki's user interface.tid b/editions/tw5.com/tiddlers/customising/Customising TiddlyWiki's user interface.tid index 78990f453..bf3357fae 100644 --- a/editions/tw5.com/tiddlers/customising/Customising TiddlyWiki's user interface.tid +++ b/editions/tw5.com/tiddlers/customising/Customising TiddlyWiki's user interface.tid @@ -45,7 +45,7 @@ Special tags assign special behaviour or appearance to all of the tiddlers to wh For example: -* $:/tags/Macro causes the macros defined in a tiddler to be available globally +* $:/tags/Global causes the definitions in a tiddler to be available globally * $:/tags/Stylesheet causes the tiddler to be interpreted as a CSS stylesheet * $:/tags/SideBar causes the tiddler to be displayed as a sidebar tab diff --git a/editions/tw5.com/tiddlers/definitions/Federatial.tid b/editions/tw5.com/tiddlers/definitions/Federatial.tid index b2ebdf83b..ce256709d 100644 --- a/editions/tw5.com/tiddlers/definitions/Federatial.tid +++ b/editions/tw5.com/tiddlers/definitions/Federatial.tid @@ -1,9 +1,21 @@ created: 20130825154900000 modified: 20170718160846820 +modified: 20221204165636777 tags: Definitions title: Federatial type: text/vnd.tiddlywiki -Federatial Limited is a software consultancy founded by JeremyRuston, the creator of TiddlyWiki. Federatial helps organisations explore new user interaction concepts through rapid prototyping of sophisticated web-based tools. +Federatial Limited helps organisations explore new user interaction concepts through rapid prototyping of sophisticated web-based tools. Services include: + +* Consultancy advice on TiddlyWiki adoption +* Development of custom solutions based on TiddlyWiki +* Multi-user TiddlyWiki hosting – no outages since 2016 +* Sponsorship of TiddlyWiki core development See https://federatial.com/ and https://twitter.com/federatial for more information. + +JeremyRuston founded Federatial Limited in 2011 to support his work on TiddlyWiki for the advertised 25 years. Since then, Federatial has been privileged to have worked with a wide range of fantastic clients in very different sectors, on some very diverse projects: + +* For a law firm in the Washington DC, developing a custom multi-user ~TiddlyWiki application. It replaced a Microsoft Word document hosted on ~SharePoint that had grown to 18,000 pages and 10 million words, and was increasingly unwieldy to manage. We converted the document to a non-linear TiddlyWiki structure. Startup, searching and browsing are an order of magnitude faster than using Word and ~SharePoint +* For a publishing firm in Paris, devising a new TiddlyWiki-based format for interactive electronic publications (including conversion from the established EPUB format). See https://twpub-tools.org/ +* For a charity in London, maintaining a multiuser instance of TiddlyWiki running on Amazon's serverless infrastructure. It has more than 1,000 users, and over 15,000 tiddlers in 500 interlinked wikis. See https://manuals.annafreud.org/ambit diff --git a/editions/tw5.com/tiddlers/definitions/Git.tid b/editions/tw5.com/tiddlers/definitions/Git.tid new file mode 100644 index 000000000..41e3711fc --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Git.tid @@ -0,0 +1,9 @@ +created: 20230723073000469 +modified: 20230723073046462 +tags: Definitions +title: Git +type: text/vnd.tiddlywiki + +>Git (/ɡɪt/) is a distributed version control system that tracks changes in any set of computer files, usually used for coordinating work among programmers collaboratively developing source code during software development. Its goals include speed, data integrity, and support for distributed, non-linear workflows (thousands of parallel branches running on different computers). +> +>https://en.wikipedia.org/wiki/Git diff --git a/editions/tw5.com/tiddlers/definitions/GitHub.tid b/editions/tw5.com/tiddlers/definitions/GitHub.tid index adbe968bd..06b24c710 100644 --- a/editions/tw5.com/tiddlers/definitions/GitHub.tid +++ b/editions/tw5.com/tiddlers/definitions/GitHub.tid @@ -1,13 +1,15 @@ created: 20140910212609354 -modified: 20190408173002622 +modified: 20230723074351846 tags: Definitions title: GitHub type: text/vnd.tiddlywiki -GitHub is a hosting service for distributed projects that use git as their version-control system. It allows free hosting and management of open-source projects and facilitates collaborative developement on the source code. Using GitHub for non-open-source endeavors requires additional fees. +GitHub is a hosting service for distributed projects that use git as their version-control system. It allows free hosting and management of open-source projects and facilitates collaborative development on the source code. Using ~GitHub for non-open-source endeavours requires additional fees. -The code and documentation of TiddlyWiki is hosted on GitHub at: +The code and documentation of TiddlyWiki is hosted on ~GitHub at: https://github.com/Jermolene/TiddlyWiki5 -GitHub also offer a free web hosting service called [[GitHub Pages|https://pages.github.com/]] that can be used directly from the single file configuration. See [[Saving to a Git service]]. +~GitHub also offer a free web hosting service called [[GitHub Pages|https://pages.github.com/]] that can be used directly from the single file configuration. See [[Saving to a Git service]]. + +An alternative to ~GitHub is GitLab \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/definitions/GitLab.tid b/editions/tw5.com/tiddlers/definitions/GitLab.tid new file mode 100644 index 000000000..a0f031f6a --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/GitLab.tid @@ -0,0 +1,13 @@ +created: 20230723072527781 +modified: 20230723073955715 +tags: Definitions +title: GitLab +type: text/vnd.tiddlywiki + +>GitLab Inc. is an open-core company that operates ~GitLab, a ~DevOps software package which can develop, secure, and operate software. The open source software project was created by Ukrainian developer Dmytro Zaporozhets and Dutch developer Sytse Sijbrandij +> +>https://en.wikipedia.org/wiki/GitLab + +Both GitLab and GitHub use [[Git]] a distributed version control system, that can be used to store, view and edit TiddlyWiki wikis using [[GitLab Pages|https://docs.gitlab.com/ee/user/project/pages/]] + +Learn more at: [[Saving to a Git service]] diff --git a/editions/tw5.com/tiddlers/definitions/HTML Block Elements.tid b/editions/tw5.com/tiddlers/definitions/HTML Block Elements.tid new file mode 100644 index 000000000..373ce9b45 --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/HTML Block Elements.tid @@ -0,0 +1,9 @@ +created: 20220818091959523 +modified: 20220818092101307 +tags: Definitions +title: HTML Block Elements +type: text/vnd.tiddlywiki + +<<< +HTML (Hypertext Markup Language) elements historically were categorized as either "block-level" elements or "inline-level" elements. Since this is a presentational characteristic it is nowadays specified by CSS in the Flow Layout. A Block-level element occupies the entire horizontal space of its parent element (container), and vertical space equal to the height of its contents, thereby creating a "block". +<<< https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements diff --git a/editions/tw5.com/tiddlers/definitions/Markdown.tid b/editions/tw5.com/tiddlers/definitions/Markdown.tid new file mode 100644 index 000000000..8c04a9b35 --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Markdown.tid @@ -0,0 +1,10 @@ +created: 20220727090611178 +modified: 20220728191637376 +tags: Definitions +title: Markdown + +<<< +Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML). +<<[img width=140 [Tiddlyhost Logo]] + +[[Tiddlyhost.com|https://tiddlyhost.com/]] is a hosting service for TiddlyWiki created by Simon Baird. Once you sign up and confirm your email you can create "sites", (i.e. ~TiddlyWikis), with support for online saving. Sites can be private or public, and you can optionally list them on the taggable and searchable [[Tiddlyhost Hub|https://tiddlyhost.com/hub]] where they'll be discoverable by others. + +Unlike [[TiddlySpot|Saving on TiddlySpot]], [[Tiddlyhost|https://tiddlyhost.com]] is secure, open source, and has proper support for TiddlyWiki5. It also allows uploading existing ~TiddlyWiki files, supports TiddlyWikiClassic, and lets you claim ownership of your ~TiddlySpot sites. For more information see the [[FAQ|https://github.com/simonbaird/tiddlyhost/wiki/FAQ]] and the [[About|https://tiddlyhost.com/about]] page. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/definitions/Xememex.tid b/editions/tw5.com/tiddlers/definitions/Xememex.tid new file mode 100644 index 000000000..5457f23cc --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Xememex.tid @@ -0,0 +1,14 @@ +title: Xememex +tags: Definitions +created: 20230410105035569 +modified: 20230410105035569 + +[img width=340 [Xememex Logo]] + +Xememex is a multiuser TiddlyWiki from [[Federatial]]. It allows large groups of people to work together on intertwingled wikis that can share content. It is implemented as a serverless application on Amazon Web Services. + +The largest customer implementation has hundreds of online wikis with thousands of users. See https://manuals.annafreud.org/ + +Xememex is currently only available under commercial terms from Federatial. Contact [[Jeremy Ruston at Federatial|mailto:jeremy@federatial.com]] for more details. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/demonstrations/ImageGallery Example.tid b/editions/tw5.com/tiddlers/demonstrations/ImageGallery Example.tid index c9df4ac0b..e702b16b7 100644 --- a/editions/tw5.com/tiddlers/demonstrations/ImageGallery Example.tid +++ b/editions/tw5.com/tiddlers/demonstrations/ImageGallery Example.tid @@ -1,6 +1,5 @@ created: 20140809113603449 modified: 20211022195248529 -tags: Learning title: ImageGallery Example type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Fourth.tid b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Fourth.tid index dd9d0b78f..cdd9850d8 100644 --- a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Fourth.tid +++ b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Fourth.tid @@ -1,6 +1,8 @@ +caption: Fourth-Caption created: 20150221194405000 modified: 20211114013601188 tags: Contents [[Table-of-Contents Demonstrations]] title: Fourth +type: text/vnd.tiddlywiki <<.toc-lorem>> diff --git a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/SecondThreeThree.tid b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/SecondThreeThree.tid index be826c19b..c7fdf343b 100644 --- a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/SecondThreeThree.tid +++ b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/SecondThreeThree.tid @@ -2,5 +2,15 @@ created: 20150221194423000 modified: 20211114013601189 tags: SecondThree [[Table-of-Contents Demonstrations]] title: SecondThreeThree +toc-link: no +type: text/vnd.tiddlywiki + +''Important'' + +It's important that this tiddler has no "child" to be able to visually test every possible toc code-path. + +* This tiddler has a field ''toc-link: no'' +* Do not tag any other tiddler with the title of this one + + -<<.toc-lorem>> diff --git a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Third.tid b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Third.tid index f8a51f8d2..7e2c7c7e1 100644 --- a/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Third.tid +++ b/editions/tw5.com/tiddlers/demonstrations/TableOfContents/Third.tid @@ -1,7 +1,9 @@ +caption: Third-Caption created: 20150221194436000 list: ThirdOne ThirdTwo ThirdThree modified: 20211114013601191 tags: Contents [[Table-of-Contents Demonstrations]] title: Third +type: text/vnd.tiddlywiki <<.toc-lorem>> diff --git a/editions/tw5.com/tiddlers/features/Core Icons.tid b/editions/tw5.com/tiddlers/features/Core Icons.tid new file mode 100644 index 000000000..9799f48d7 --- /dev/null +++ b/editions/tw5.com/tiddlers/features/Core Icons.tid @@ -0,0 +1,41 @@ +title: Core Icons +tags: Features +modified: 20230423103154329 +created: 20230423103154329 + + +!! Introduction + +TiddlyWiki includes over 100 custom vector icons. They feature in the user interface and are also available for authors to use in their own applications. See [[Icon Gallery]] for a complete listing. + +!! Usage + +The core icons are used by transcluding them. For example: + +<> + +The core icons are parameterised. The first parameter `size` specified the size at which the icon should be rendered: + +< +""">> + +Here is an example of dynamically resizing icons: + +< +<$text text={{{ [addsuffix[px]] }}} /> +<$transclude $tiddler="$:/core/icon" size=<>/> + +""">> + +Some icons take further parameters to customise how they are rendered. For example, the $:/core/images/new-journal-button icon takes an additional parameter `day` that specifies the day of the month that should be shown on the calendar. It defaults to the current date if not specified + +< +""">> + +The core icons are implemented as embedded [[SVG elements|Using SVG]], and not as full-blown SVG images. This means that they can be styled using CSS. For example, the CSS property `fill` can be used to change the colour of the icons. For example: + +<{{$:/core/images/opacity}} +""">> diff --git a/editions/tw5.com/tiddlers/features/DateFormat.tid b/editions/tw5.com/tiddlers/features/DateFormat.tid index db6a1f3e4..f918d9a99 100644 --- a/editions/tw5.com/tiddlers/features/DateFormat.tid +++ b/editions/tw5.com/tiddlers/features/DateFormat.tid @@ -1,14 +1,14 @@ created: 20140418142957325 -modified: 20221121131150032 +modified: 20230226144359284 tags: Features title: DateFormat type: text/vnd.tiddlywiki -The default representation of dates is a compact string such as `20211002153802059`. For example, the `created` and `modified` fields are stored like this. +The default representation of dates is a compact string such as <<.value 20211002153802059>>. The associated template is `[UTC]YYYY0MM0DD0hh0mm0ss0XXX`. For example, the <<.field created>> and <<.field modified>> fields are stored like this. -The display format for this string can be controlled with a template. For example, transcluding the `modified` field automatically applies a template to display the date as `Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)`. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget: +The display format for this string can be controlled with a template. For example, transcluding the <<.field modified>> field automatically applies a template to display the date as <<.value "Sat Oct 02 2021 17:40:50 GMT+0200 (Central European Summer Time)">>. A few widgets and filter operators allow you to manually specify a template, for example the ViewWidget: -`<$view field=modified format=date template=“DDth mmm YYYY 0hh:0mm:0ss” />` +`<$view field=modified format=date template="DDth mmm YYYY 0hh:0mm:0ss" />` The date string is processed with the following substitutions: @@ -52,7 +52,7 @@ The date string is processed with the following substitutions: Note that other text is passed through unchanged, allowing commas, colons or other separators to be used. -The `{era:BCE||CE}` notation can specify different strings for years that are negative, zero or positive. For example `{era:BC|Z|AD}` would display `BC` for negative years, `AD` for positive years, and `Z` for year zero. +The `{era:BCE||CE}` notation can specify different strings for years that are negative, zero or positive. For example `{era:BC|Z|AD}` would display <<.value BC>> for negative years, <<.value AD>> for positive years, and <<.value Z>> for year zero. ! Examples @@ -61,7 +61,7 @@ The `{era:BCE||CE}` notation can specify different strings for years that are ne |`DDth MMM \M\M\M YYYY` |16th February MMM 2011 | |`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 | -!! Using `TIMESTAMP` to calculate time difference +!! Using <<.value TIMESTAMP>> to calculate time difference You can calculate the difference between two dates by doing the following: @@ -71,10 +71,11 @@ You can calculate the difference between two dates by doing the following: Here is an example of calculating the number of days that passed between creation and last modification of current tiddler: -* Fields `modified` and `created` contain their respective datetimes in the format `YYYYMMDDHHMMSSmmm` so convert them to timestamps -* `86400000` is the number of milliseconds in a day (1000 * 60 * 60 * 24) +* Convert the <<.field created>> and <<.field modified>> fields to timestamps +* Divide their difference by <<.value 86400000>> which is the number of milliseconds in a day +** 1000 milliseconds per second × 60 seconds per minute × 60 minutes per hour × 24 hours per day = 86,400,000 milliseconds per day -<$macrocall $name=".example" n="0" eg="""<$let +<$macrocall $name=".example" n="0" eg="""<$let timestamp-modified={{{ [{!!modified}format:date[TIMESTAMP]] }}} timestamp-created={{{ [{!!created}format:date[TIMESTAMP]] }}} difference-days={{{ [subtractdivide[86400000]floor[]] }}}> diff --git a/editions/tw5.com/tiddlers/features/Deserializers.tid b/editions/tw5.com/tiddlers/features/Deserializers.tid new file mode 100644 index 000000000..1da4813df --- /dev/null +++ b/editions/tw5.com/tiddlers/features/Deserializers.tid @@ -0,0 +1,20 @@ +created: 20230627093650105 +modified: 20230627094356394 +tags: Features +title: Deserializers +type: text/vnd.tiddlywiki + +Deserializer [[modules|Modules]] parse text in various formats into their JSON representation as tiddlers. The deserializer modules available in a wiki can be seen using the [[deserializers operator|deserializers Operator]] and can be used with the [[deserialize Operator]]. + +The TiddlyWiki core provides the following deserializers: + +|!Deserializer |!Description | +|(DOM)|Extracts tiddlers from a DOM node, should not be used with the <<.op deserialize[]>> operator | +|application/javascript|Parses a JavaScript module as a tiddler extracting fields from the header comment| +|application/json|Parses [[JSON|JSON in TiddlyWiki]] into tiddlers| +|application/x-tiddler|Parses the [[.tid file format|TiddlerFiles]] as a tiddler| +|application/x-tiddler-html-div|Parses the [[
.tiddler file format|TiddlerFiles]] as a tiddler| +|application/x-tiddlers|Parses the [[MultiTiddlerFile format|MultiTiddlerFiles]] as tiddlers| +|text/css|Parses CSS as a tiddler extracting fields from the header comment| +|text/html|Parses an HTML file into tiddlers. Supports ~TiddlyWiki Classic HTML files, ~TiddlyWiki5 HTML files and ordinary HTML files| +|text/plain|Parses plain text as a tiddler| \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/features/JSON in TiddlyWiki.tid b/editions/tw5.com/tiddlers/features/JSON in TiddlyWiki.tid index 2f2edd09f..cd827ddb6 100644 --- a/editions/tw5.com/tiddlers/features/JSON in TiddlyWiki.tid +++ b/editions/tw5.com/tiddlers/features/JSON in TiddlyWiki.tid @@ -2,7 +2,7 @@ title: JSON in TiddlyWiki tags: Features type: text/vnd.tiddlywiki created: 20220427174702859 -modified: 20220427174702859 +modified: 20220611104737314 !! Introduction diff --git a/editions/tw5.com/tiddlers/features/Modals.tid b/editions/tw5.com/tiddlers/features/Modals.tid index 56b596947..9cf663845 100644 --- a/editions/tw5.com/tiddlers/features/Modals.tid +++ b/editions/tw5.com/tiddlers/features/Modals.tid @@ -6,16 +6,19 @@ type: text/vnd.tiddlywiki Modals (or "wizards") fade the main TiddlyWiki window to display an isolated tiddler that must be explicitly dismissed by the user. -The tiddler to be displayed can contain the following optional fields that are used to customize the modal: +The tiddler to be displayed can contain the following optional fields that are used to customise the modal: |!Field |!Description | |footer|The footer text for the modal| |subtitle|The subtitle text for a modal, displayed in a `h3` html tag| |class|An additional class to apply to the modal wrapper| |help|An optional external link that will be displayed at the left of the footer with the text "Help"| +|mask-closable|When set to ''yes'' or ''true'', will close the modal dialog when the mask (area outside the modal) is clicked| Note that the footer and subtitle fields are not limited to plain text, and wiki text features such as widgets and transclusions can be used as well. Modals are displayed with the [[WidgetMessage: tm-modal]]. <$button message="tm-modal" param="SampleWizard">Open demo modal + +<<.tip """<$macrocall $name=".from-version" version="5.2.4"/> allow using "mask-closable" field""">> diff --git a/editions/tw5.com/tiddlers/features/StartupActions.tid b/editions/tw5.com/tiddlers/features/StartupActions.tid index 79a23b3d9..596b92564 100644 --- a/editions/tw5.com/tiddlers/features/StartupActions.tid +++ b/editions/tw5.com/tiddlers/features/StartupActions.tid @@ -33,10 +33,10 @@ The initial startup actions are useful for customising TiddlyWiki according to e <$action-setfield $tiddler="$:/language" text={{{ [[$:/languages/en-GB]] [plugin-type[language]sort[description]removeprefix[$:/languages/]] +[prefix{$:/info/browser/language}] ~[[en-GB]] +[addprefix[$:/languages/]] }}}/> ``` -Note that global macros are not available within initial startup action tiddlers by default. If you need to access them then you'll need to explicitly include them with an ''import'' [[pragma|Pragma]] at the top of the tiddler: +Note that global macros are not available within initial startup action tiddlers by default. If you need to access them then you'll need to explicitly include them with an [[Pragma: \import]] at the top of the tiddler: ``` -\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] +\import [subfilter{$:/core/config/GlobalImportFilter}] ``` !! Post-Render Startup Actions diff --git a/editions/tw5.com/tiddlers/filters/Conditional Operators.tid b/editions/tw5.com/tiddlers/filters/Conditional Operators.tid index 7028e6dad..6d21e0864 100644 --- a/editions/tw5.com/tiddlers/filters/Conditional Operators.tid +++ b/editions/tw5.com/tiddlers/filters/Conditional Operators.tid @@ -1,12 +1,12 @@ created: 20190802113703788 -modified: 20190802132727925 +modified: 20230501175143648 tags: Filters title: Conditional Operators type: text/vnd.tiddlywiki -<<.from-version "5.1.20">>The conditional filter operators allow ''if-then-else'' logic to be expressed within filters. +<<.from-version "5.1.20">>The conditional filter operators allow for ''if-then-else'' logic to be expressed within filters. -The foundation is the convention that an empty list can be used to represent the boolean value ''false'' and a list with at one (or more) entries to represent ''true''. +The foundation is the convention that an empty list can be used to represent the Boolean value <<.value false>> and a list with at one (or more) entries to represent <<.value true>>. The conditional operators are: @@ -19,10 +19,12 @@ The conditional operators are: These operators can be combined. For example: -<<.inline-operator-example "[[New Tiddler]is[missing]then[I am missing]else[No I am not missing]]">> +<<.operator-example 1 "[[New Tiddler]is[missing]then[I am missing]else[No I am not missing]]">> -The [[else Operator]] can be used to apply a defaults for missing values. In this example, we take advantage of the fact that the [[get Operator]] returns an empty list if the field or tiddler does not exist: +The <<.olink else>> operator can be used to apply a defaults for missing values. In this example, we take advantage of the fact that the <<.olink get>> operator returns an empty list if the field or tiddler does not exist: -<<.inline-operator-example "[[HelloThere]get[custom-field]else[default-value]]">> +<<.operator-example 2 "[[HelloThere]get[custom-field]else[default-value]]">> -<> +! Filter Run Prefixes + +The [[:then|:then Filter Run Prefix]] and [[:else|:else Filter Run Prefix]] filter run prefixes serve a similar purpose as the conditional operators. Refer to their documentation for more information. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/applypatches Operator.tid b/editions/tw5.com/tiddlers/filters/applypatches Operator.tid new file mode 100644 index 000000000..93bb0258c --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/applypatches Operator.tid @@ -0,0 +1,15 @@ +caption: applypatches +created: 20230304154824762 +modified: 20230304154826621 +op-purpose: applies a set of patches to transform the input +op-input: a [[selection of titles|Title Selection]] +op-parameter: a string containing patches from the [[makepatches Operator]] +op-parameter-name: P +op-output: the transformed input to which the patches <<.place P>> have been applied +tags: [[Filter Operators]] [[String Operators]] +title: applypatches Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.2.6">> + +<<.operator-examples "makepatches and applypatches">> diff --git a/editions/tw5.com/tiddlers/filters/decodebase64 Operator.tid b/editions/tw5.com/tiddlers/filters/decodebase64 Operator.tid new file mode 100644 index 000000000..0d3a61920 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/decodebase64 Operator.tid @@ -0,0 +1,21 @@ +caption: decodebase64 +op-input: a [[selection of titles|Title Selection]] +op-output: the input with base 64 decoding applied +op-suffix: optional: `binary` to produce binary output, `urlsafe` for URL-safe input +op-parameter: +op-parameter-name: +op-purpose: apply base 64 decoding to a string +tags: [[Filter Operators]] [[String Operators]] +title: decodebase64 Operator +type: text/vnd.tiddlywiki +from-version: 5.2.6 + +See Mozilla Developer Network for details of [[base 64 encoding|https://developer.mozilla.org/en-US/docs/Glossary/Base64]]. TiddlyWiki uses [[library code from @nijikokun|https://gist.github.com/Nijikokun/5192472]] to handle the conversion. + +The input strings must be base64 encoded. The output strings are the text (or binary data) decoded from base64 format. + +The optional `binary` suffix, if present, changes how the input is processed. The input is normally assumed to be [[UTF-8|https://developer.mozilla.org/en-US/docs/Glossary/UTF-8]] text encoded in base64 form (such as what the <<.op "encodebase64">> operator produces), so only certain byte sequences in the input are valid. If the input is binary data encoded in base64 format (such as an image, audio file, video file, etc.), then use the optional `binary` suffix, which will allow all byte sequences. Note that the output will then be binary, ''not'' text, and should probably not be passed into further filter operators. + +The optional `urlsafe` suffix, if present, causes the decoder to assume that the base64 input uses `-` and `_` instead of `+` and `/` for the 62nd and 63rd characters of the base64 "alphabet", which is usually referred to as "URL-safe base64" or "bae64url". + +<<.operator-examples "decodebase64">> diff --git a/editions/tw5.com/tiddlers/filters/deserialize Operator.tid b/editions/tw5.com/tiddlers/filters/deserialize Operator.tid new file mode 100644 index 000000000..7205d09c6 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/deserialize Operator.tid @@ -0,0 +1,17 @@ +caption: deserialize +created: 20230601195749377 +from-version: 5.3.0 +modified: 20230627094109762 +op-input: a selection of strings +op-output: JSON representations of tiddlers extracted from input titles. +op-parameter: the deserializer module to be used to extract tiddlers from the input +op-purpose: extract JSON representation of tiddlers from the input strings +tags: [[Filter Operators]] [[Special Operators]] +title: deserialize Operator +type: text/vnd.tiddlywiki + +{{Deserializers}} + + + +<<.operator-examples "deserialize">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/deserializers Operator.tid b/editions/tw5.com/tiddlers/filters/deserializers Operator.tid index 2501553e8..7691be970 100644 --- a/editions/tw5.com/tiddlers/filters/deserializers Operator.tid +++ b/editions/tw5.com/tiddlers/filters/deserializers Operator.tid @@ -1,14 +1,14 @@ caption: deserializers created: 20210506115203172 from-version: 5.2.0 -modified: 20210506130322593 +modified: 20230627094238610 op-input: ignored op-output: the title of each available deserializer op-parameter: none -tags: [[Filter Operators]] [[Special Operators]] [[Selection Constructors]] +tags: [[Filter Operators]] [[Special Operators]] [[Selection Constructors]] title: deserializers Operator type: text/vnd.tiddlywiki -<<.tip "You can specify a specific deserializer for a DropzoneWidget to use">> +<<.tip "You can specify a specific [[deserializer|Deserializers]] for a DropzoneWidget to use">> <<.operator-examples "deserializers">> diff --git a/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid b/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid new file mode 100644 index 000000000..a7943d726 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/encodebase64 Operator.tid @@ -0,0 +1,21 @@ +caption: encodebase64 +op-input: a [[selection of titles|Title Selection]] +op-output: the input with base 64 encoding applied +op-suffix: optional: `binary` to treat input as binary data, `urlsafe` for URL-safe output +op-parameter: +op-parameter-name: +op-purpose: apply base 64 encoding to a string +tags: [[Filter Operators]] [[String Operators]] +title: encodebase64 Operator +type: text/vnd.tiddlywiki +from-version: 5.2.6 + +See Mozilla Developer Network for details of [[base 64 encoding|https://developer.mozilla.org/en-US/docs/Glossary/Base64]]. TiddlyWiki uses [[library code from @nijikokun|https://gist.github.com/Nijikokun/5192472]] to handle the conversion. + +The input strings are interpreted as [[UTF-8 encoded|https://developer.mozilla.org/en-US/docs/Glossary/UTF-8]] text (or binary data instead if the `binary` suffix is present). The output strings are base64 encoded. + +The optional `binary` suffix, if present, causes the input string to be interpreted as binary data instead of text. Normally, an extra UTF-8 encoding step will be added before the base64 output is produced, so that emojis and other Unicode characters will be encoded correctly. If the input is binary data, such as an image, audio file, video, etc., then the UTF-8 encoding step would produce incorrect results, so using the `binary` suffix causes the UTF-8 encoding step to be skipped. + +The optional `urlsafe` suffix, if present, will use the alternate "URL-safe" base64 encoding, where `-` and `_` are used instead of `+` and `/` respectively, allowing the result to be used in URL query parameters or filenames. + +<<.operator-examples "encodebase64">> diff --git a/editions/tw5.com/tiddlers/filters/encodeuricomponent_Operator.tid b/editions/tw5.com/tiddlers/filters/encodeuricomponent_Operator.tid index 8aa961a96..0ff9886ca 100644 --- a/editions/tw5.com/tiddlers/filters/encodeuricomponent_Operator.tid +++ b/editions/tw5.com/tiddlers/filters/encodeuricomponent_Operator.tid @@ -1,6 +1,6 @@ caption: encodeuricomponent created: 20161017152747386 -modified: 20161017152809900 +modified: 20230119174350062 op-input: a [[selection of titles|Title Selection]] op-output: the input with URI component encoding applied op-parameter: @@ -13,4 +13,6 @@ from-version: 5.1.14 See Mozilla Developer Network for details of the [[encodeURIComponent|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent]] operation. +<<.from-version "5.2.6">> In addition to the characters mentioned in the article above, the following additional characters are also percent encoded: `!'()*` + <<.operator-examples "encodeuricomponent">> diff --git a/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid b/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid new file mode 100644 index 000000000..da209b035 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/Hamlet.tid @@ -0,0 +1,11 @@ +created: 20230304161453213 +modified: 20230304162156826 +tags: [[Operator Examples]] +title: Hamlet +type: application/json + +{ + "Shakespeare-old": "Hamlet: Do you see yonder cloud that's almost in shape of a camel?\nPolonius: By the mass, and 'tis like a camel, indeed.\nHamlet: Methinks it is like a weasel.\nPolonius: It is backed like a weasel.\nHamlet: Or like a whale?\nPolonius: Very like a whale.\n-- Shakespeare", + "Shakespeare-new": "Hamlet: Do you see the cloud over there that's almost the shape of a camel?\nPolonius: By golly, it is like a camel, indeed.\nHamlet: I think it looks like a weasel.\nPolonius: It is shaped like a weasel.\nHamlet: Or like a whale?\nPolonius: It's totally like a whale.\n-- Shakespeare", + "Trekkie-old": "Kirk: Do you see yonder cloud that's almost in shape of a Klingon?\nSpock: By the mass, and 'tis like a Klingon, indeed.\nKirk: Methinks it is like a Vulcan.\nSpock: It is backed like a Vulcan.\nKirk: Or like a Romulan?\nSpock: Very like a Romulan.\n-- Trekkie" +} \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid new file mode 100644 index 000000000..5170809b7 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/deserialize Operator (Examples).tid @@ -0,0 +1,29 @@ +created: 20230601200356736 +modified: 20230602105036887 +tags: [[Operator Examples]] [[deserialize Operator]] +title: deserialize Operator (Examples) +type: text/vnd.tiddlywiki + +\define html-data() + + + + + Test Data + + + + + + + + +\end + +This example uses the predefined variable `html-data`: +<$codeblock code=<> language="HTML"/> + +<<.operator-example 1 "[deserialize[text/html]]">> diff --git a/editions/tw5.com/tiddlers/filters/examples/format Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/format Operator (Examples).tid index c1d79ea8c..b6ad505a1 100644 --- a/editions/tw5.com/tiddlers/filters/examples/format Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/format Operator (Examples).tid @@ -1,5 +1,5 @@ created: 20201020102735123 -modified: 20220611104737314 +modified: 20230226135641976 tags: [[Operator Examples]] [[format Operator]] title: format Operator (Examples) type: text/vnd.tiddlywiki @@ -15,20 +15,23 @@ Created date with a format string supplied as operator parameter: Modified date shown as a relative date: <<.operator-example 3 "[[HelloThere]get[modified]format:relativedate[]]">> +Get the date and time exactly 24 hours (86,400,000 milliseconds) from now: +<<.operator-example 4 "[format:date[TIMESTAMP]add[86400000]format:timestamp[DDth mmm YYYY 0hh:0mm:0ss]]">> + A tiddler title with spaces formatted as a title list: -<<.operator-example 4 """[[Hello There]format:titlelist[]]""">> +<<.operator-example 5 """[[Hello There]format:titlelist[]]""">> All tiddler titles tagged with <> formatted as a title list: -<<.operator-example 5 """[tag[TableOfContents]format:titlelist[]]""">> +<<.operator-example 6 """[tag[TableOfContents]format:titlelist[]]""">> A JSON string formatted as JSON – note how the JSON string is normalised to remove the duplicated properties: -<<.operator-example 6 """[[{"one":"first","one":"another","two":"second"}]format:json[]]""">> +<<.operator-example 7 """[[{"one":"first","one":"another","two":"second"}]format:json[]]""">> <<.tip "To create a string to save a [[title list|Title List]] into a list field, use `format:titlelist[]` with the [[join operator|join Operator]]">> -<<.operator-example 6 """[tag[TableOfContents]format:titlelist[]join[ ]]""">> +<<.operator-example 8 """[tag[TableOfContents]format:titlelist[]join[ ]]""">> For example, to save titles tagged `TableOfContents` to the titles field of the tiddler [[format titlelist test]]: <$macrocall $name='wikitext-example-without-html' -src='<$button> test +src='<$button>Try it <$action-setfield $tiddler="format titlelist test" titles={{{ [tag[TableOfContents]format:titlelist[]join[ ]] }}}/> '/> diff --git a/editions/tw5.com/tiddlers/filters/examples/get.tid b/editions/tw5.com/tiddlers/filters/examples/get.tid index c49d876d6..c85a38f3e 100644 --- a/editions/tw5.com/tiddlers/filters/examples/get.tid +++ b/editions/tw5.com/tiddlers/filters/examples/get.tid @@ -1,9 +1,22 @@ created: 20150118134611000 -modified: 20150124201839000 +modified: 20230325163424379 +myfield: tags: [[get Operator]] [[Operator Examples]] title: get Operator (Examples) type: text/vnd.tiddlywiki <<.operator-example 1 "[all[current]get[draft.of]]" "the title of the tiddler of which the current tiddler is a draft">> -<<.operator-example 2 "[get[tags]]">> -<<.operator-example 3 "[each[tags]get[tags]]">> + +<<.operator-example 2 "[get[tags]]" "returns the tags of all tiddlers without de-duplication">> + +<<.operator-example 3 "[get[tags]unique[]]" "returns the tags of all tiddlers with de-duplication">> + +<<.tip """If a data tiddler contains a field with an empty value, the empty string is not appended to the results.""">> + +<<.operator-example 4 "[all[current]get[myfield]]" "the empty value of field <<.field myfield>> is not returned by the <<.olink get>> operator">> + +<<.operator-example 5 "[all[current]has:field[myfield]] :map[get[myfield]]" "also returns the empty string">> +The above example works by first checking if the input title has the field <<.field myfield>> and then using the [[Map Filter Run Prefix]] to replace the title with their value of that field. If the input tiddler does not have the field, an empty <<.em selection>> is returned. The subsequent [[Map Filter Run Prefix]] outputs an empty <<.em string>> when its run returns an empty [[selection|Title Selection]] (because the field is empty). + +<<.operator-example 6 "[all[tiddlers]] :filter[get[created]compare:date:lt{HelloThere!!created}]" "return all tiddlers that are older than [[HelloThere]]">> +The above example demonstrates two different ways of accessing field values in filters: Use <<.olink get>> when the title is not known in advance as with the [[Filter Filter Run Prefix]] where <<.var currentTiddler>> is set to the current input title. Use a [[TextReference]] as an indirect [[Filter Parameter]] when the title is known. diff --git a/editions/tw5.com/tiddlers/filters/examples/getindex.tid b/editions/tw5.com/tiddlers/filters/examples/getindex.tid index 780c09946..6dab64c77 100644 --- a/editions/tw5.com/tiddlers/filters/examples/getindex.tid +++ b/editions/tw5.com/tiddlers/filters/examples/getindex.tid @@ -1,8 +1,19 @@ created: 20150203140000000 -modified: 20170608150301791 +modified: 20230325163543621 tags: [[getindex Operator]] [[Operator Examples]] title: getindex Operator (Examples) type: text/vnd.tiddlywiki -<<.operator-example 1 "[[$:/palettes/Vanilla]getindex[background]]" "returns the value at index ''background'' of the [[DataTiddler|DataTiddlers]] [[$:/palettes/Vanilla]]">> -<<.operator-example 2 "[all[shadows+tiddlers]tag[$:/tags/Palette]getindex[background]]" "returns all background colors defined in any of the ColourPalettes">> \ No newline at end of file +<<.operator-example 1 "[[$:/palettes/Vanilla]getindex[background]]" "returns the value of property <<.value background>> of the [[DataTiddler|DataTiddlers]] [[$:/palettes/Vanilla]]">> + +<<.operator-example 2 "[all[shadows+tiddlers]tag[$:/tags/Palette]getindex[background]]" "returns all background colors defined in any of the ColourPalettes (notice the duplicates in the resulting list)">> + +<<.tip """If a data tiddler contains a property with an empty value, the empty string is not appended to the results.""">> + +<<.operator-example 3 "[[ListopsData]getindex[DataIndex]]" "the empty value of the property <<.field ~DataIndex>> in [[ListopsData]] is not returned by the <<.olink getindex>> operator">> + +<<.operator-example 4 "[[ListopsData]has:index[DataIndex]] :map[getindex[DataIndex]]" "also returns the empty string">> +The above example works by first checking if the input title has the property <<.field ~DataIndex>> and then using the [[Map Filter Run Prefix]] to replace the title with their value of that property. If the input tiddler does not have the property, an empty <<.em selection>> is returned. The subsequent [[Map Filter Run Prefix]] outputs an empty <<.em string>> when its run returns an empty [[selection|Title Selection]] (because the property is empty). + +<<.operator-example 5 "[[$:/palettes/Vanilla]indexes[]] :filter[[$:/palettes/Vanilla]getindexcount[]compare:number:eq[0]]" "returns those colors in [[$:/palettes/Vanilla]] which are defined, but have no value assigned">> +In the above example, <<.olink count>> is used to check if <<.olink getindex>> returns a result (i.e. the corresponding property has a value) or not. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/jsonset.tid b/editions/tw5.com/tiddlers/filters/examples/jsonset.tid new file mode 100644 index 000000000..8cd1d1d61 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/jsonset.tid @@ -0,0 +1,59 @@ +created: 20231204112944341 +modified: 20231204115056732 +tags: [[Operator Examples]] [[jsonset Operator]] +title: jsonset Operator (Examples) + +<$let object-a="""{ + "a": "one", + "b": "", + "c": "three", + "d": { + "e": "four", + "f": [ + "five", + "six", + true, + false, + null + ], + "g": { + "x": "max", + "y": "may", + "z": "maize" + } + } +} +""" +object-b="""{"a":"one","b":"","c":1.618,"d":{"e":"four","f":["five","six",true,false,null]}}"""> + +The examples below assume the following JSON object is contained in the variable `object-a`: + +
<>
+ +<<.operator-example 1 "[jsonset[d],[Jaguar]]">> +<<.operator-example 2 "[jsonset[d],[f],[Panther]]">> +<<.operator-example 3 "[jsonset[d],[f],[-1],[Elephant]]">> +<<.operator-example 4 "[jsonset[d],[f],[-2],[Elephant]]">> +<<.operator-example 5 "[jsonset[d],[f],[-4],[Elephant]]">> +<<.operator-example 6 "[jsonset[Panther]]" "If only a single parameter is specified, it replaces the entire JSON object">> +<<.operator-example 7 "[jsonset[]]" "If only a single blank parameter is specified, no changes are made to the JSON object">> + + +The examples below assume the following JSON object is contained in the variable `object-b`: + +
<>
+ +<<.operator-example 8 "[jsonset[]]" "If only a single blank parameter is specified, no changes are made to the JSON object">> +<<.operator-example 9 "[jsonset[],[Antelope]]" "If the property to be set is blank, the entire JSON object is replaced">> +<<.operator-example 10 "[jsonset:number[],[not a number]]" "invalid numbers are interpreted as zero">> +<<.operator-example 11 "[jsonset[id],[Antelope]]" "nonexistent top level properties are added to the object">> +<<.operator-example 19 "[jsonset[missing],[id],[Antelope]]" "nonexistent nested properties are are ignored">> +<<.operator-example 12 "[jsonset:notatype[id],[Antelope]]" "invalid type suffix is interpreted as the default string type">> +<<.operator-example 13 "[jsonset:boolean[id],[false]]">> +<<.operator-example 14 "[jsonset:boolean[id],[Antelope]]" "invalid boolean value causes no assignment to be made">> +<<.operator-example 15 "[jsonset:number[id],[42]]">> +<<.operator-example 16 "[jsonset:null[id]]">> +<<.operator-example 17 "[jsonset:array[d],[f],[5]]">> +<<.operator-example 18 "[jsonset:object[d],[f],[5]]">> + +<<.operator-example 20 "[] [] :and[jsonset[b],[two]]" "If the input consists of multiple JSON objects with matching properties, the value is set for all of them">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid index ead9ffb38..39113ea38 100644 --- a/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid @@ -1,9 +1,11 @@ -created: 20171029155046637 -modified: 20171029155227382 -tags: [[Operator Examples]] [[stringify Operator]] +created: 20230922121858167 +modified: 20230922122333325 +tags: [[Operator Examples]] [[jsonstringify Operator]] title: jsonstringify Operator (Examples) type: text/vnd.tiddlywiki -<<.operator-example 1 """[[Title with "double quotes" and single ' and \backslash]] +[jsonstringify[]]""">> +Compare the encoding of quotes and control characters in the first example with the analogue [[example for the stringify operator|stringify Operator (Examples)]]. +<<.operator-example 1 """[[Backslash \, double quote ", single quote ', tab , line feed +]] +[jsonstringify[]]""">> <<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[jsonstringify[]]""">> -<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[jsonstringify:rawunicode[]]""">> +<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[jsonstringify:rawunicode[]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid new file mode 100644 index 000000000..b5049e49c --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/levenshtein Operator (Examples).tid @@ -0,0 +1,21 @@ +created: 20230304183158728 +modified: 20230304183159654 +tags: [[levenshtein Operator]] [[Operator Examples]] +title: levenshtein Operator (Examples) +type: text/vnd.tiddlywiki + +Determine the Levenshtein distance between two words: + +<<.operator-example 1 "[[motel]levenshtein[money]]">> + +List the 10 tiddler titles with the smallest Levenstein distance to "~TiddlyWiki": + +<$macrocall $name='wikitext-example-without-html' +src="""
    +<$list filter="[all[tiddlers]!is[system]] :sort:number[levenshtein[TiddlyWiki]] :and[first[10]]"> +
  • +<$link /> (<$text text={{{ [all[current]levenshtein[TiddlyWiki]] }}} />) +
  • + +
+"""/> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid new file mode 100644 index 000000000..a9dd38d6e --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/makepatches and applypatches Operator (Examples).tid @@ -0,0 +1,43 @@ +created: 20230304160331362 +modified: 20230304160332927 +tags: [[makepatches Operator]] [[applypatches Operator]] [[Operator Examples]] +title: makepatches and applypatches Operator (Examples) +type: text/vnd.tiddlywiki + +These examples use the example texts in [[Hamlet]], taken from [[https://neil.fraser.name/software/diff_match_patch/demos/patch.html]] + +|^!Shakespeare's original |@@white-space: pre-wrap;{{Hamlet##Shakespeare-old}}@@ | +|^!Modern English |@@white-space: pre-wrap;{{Hamlet##Shakespeare-new}}@@ | +|^!Trekkie's Copy |@@white-space: pre-wrap;{{Hamlet##Trekkie-old}}@@ | + +
+ +Use `makepatches` to generate the set of patches to transform Shakepeare's original into Modern English: + +<<.operator-example 1 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}]">> + +Use `applypatches` to apply the patches to Shakespeare's original text: + +<<.operator-example 2 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}] :map[{Hamlet##Shakespeare-old}applypatches]">> + +In the above example, the [[Map Filter Run Prefix]] is used to pass the patches information as a parameter to `applypatches`. Inside `:map`, <<.value currentTiddler>> is set to the input title (i.e. the previously generated patches). + +The patch information from the Shakepeare texts can also be used to transform the //Trekkie's Copy// to a Modern English version: + +<<.operator-example 3 "[{Hamlet##Shakespeare-old}makepatches{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +The above examples used the character mode of `makepatches`. The `word` mode yields very similar results in this case, even when applied to the //Trekkie's Copy//. + +<<.operator-example 4 "[{Hamlet##Shakespeare-old}makepatches:words{Hamlet##Shakespeare-new}]">> + +<<.operator-example 5 "[{Hamlet##Shakespeare-old}makepatches:words{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +The `lines` mode doesn't work as well in this application: + +<<.operator-example 6 "[{Hamlet##Shakespeare-old}makepatches:lines{Hamlet##Shakespeare-new}]">> + +<<.operator-example 7 "[{Hamlet##Shakespeare-old}makepatches:lines{Hamlet##Shakespeare-new}] :map[{Hamlet##Trekkie-old}applypatches]">> + +It is better suited as a very fast algorithm to detect line-wise incremental changes to texts and store only the changes instead of multiple versions of the whole texts. + +
\ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/regexp.tid b/editions/tw5.com/tiddlers/filters/examples/regexp.tid index 161df8937..5b18a1613 100644 --- a/editions/tw5.com/tiddlers/filters/examples/regexp.tid +++ b/editions/tw5.com/tiddlers/filters/examples/regexp.tid @@ -17,5 +17,5 @@ The regular expression `[0-9]{2}` matches two consecutive digits. Because it con <$macrocall $name="wikitext-example-without-html" src="""<$set name="digit-pattern" value="[0-9]{2}"> -<]">> +<]" field:"title">> """/> diff --git a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid index a664cf7d2..4b67993b0 100644 --- a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid @@ -1,9 +1,11 @@ created: 20161017154944352 -modified: 20171029155233487 +modified: 20230922122319674 tags: [[Operator Examples]] [[stringify Operator]] title: stringify Operator (Examples) type: text/vnd.tiddlywiki -<<.operator-example 1 """[[Title with "double quotes" and single ' and \backslash]] +[stringify[]]""">> +Compare the encoding of quotes and control characters in the first example with the analogue [[example for the jsonstringify operator|jsonstringify Operator (Examples)]]. +<<.operator-example 1 """[[Backslash \, double quote ", single quote ', tab , line feed +]] +[stringify[]]""">> <<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[stringify[]]""">> -<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[stringify:rawunicode[]]""">> +<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[stringify:rawunicode[]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid new file mode 100644 index 000000000..ece8aecf6 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/substitute Operator (Examples).tid @@ -0,0 +1,37 @@ +created: 20230614225302905 +modified: 20230614233448662 +tags: [[Operator Examples]] [[substitute Operator]] +title: substitute Operator (Examples) +type: text/vnd.tiddlywiki + +\define time() morning +\define field() modified +\procedure sentence() This tiddler was last $(field)$ on ${[{!!modified}format:date[DDth MMM YYYY]]}$ +\define name() Bugs Bunny +\define address() Rabbit Hole Hill + +!Substitute <<.op substitute[]>> operator parameters +<<.operator-example 1 "[[Hi, I'm $1$ and I live in $2$]substitute[Bugs Bunny],[Rabbit Hole Hill]]">> + +!Substitute variables +This example uses the following variables: + +* name: <$codeblock code=<>/> +* address: <$codeblock code=<
>/> + +<<.operator-example 2 "[[Hi, I'm $(name)$ and I live in $(address)$]substitute[]]">> + +!Substitute variables and operator parameters +This example uses the following variable: + +* time: <$codeblock code=<