Merge branch 'master' into external-tasks

This commit is contained in:
Jeremy Ruston
2019-08-06 21:16:52 +01:00
568 changed files with 24819 additions and 17242 deletions
+23 -15
View File
@@ -2,25 +2,33 @@ language: node_js
- "node"
stages:
- name: install
if: branch = "master"
- name: test
- name: build
if: branch = "master"
- name: pre-deploy
if: branch = "master"
- name: deploy
- name: build-prerelease
if: branch = "master"
- name: build-tiddlywiki-com
if: branch = "tiddlywiki-com"
jobs:
include:
- stage: install
script: npm --force install tiddlywiki
- stage: test
script: ./bin/test.sh
- stage: build
script: ./bin/build-site.sh
- stage: pre-deploy
script: skip
- stage: deploy
script: ./bin/deploy-site.sh
- stage: build-prerelease
script:
- ./bin/travis-pre-build.sh
- export TW5_BUILD_TIDDLYWIKI='./tiddlywiki.js'
- export TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)
- export TW5_BUILD_DETAILS="Prerelease built from branch '$TRAVIS_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')"
- export TW5_BUILD_MAIN_EDITION='./editions/prerelease'
- export TW5_BUILD_OUTPUT='./output/prerelease'
- ./bin/build-site.sh
- ./bin/travis-push.sh
- stage: build-tiddlywiki-com
script:
- ./bin/travis-pre-build.sh
- export TW5_BUILD_TIDDLYWIKI='./node_modules/tiddlywiki/tiddlywiki.js'
- export TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)
- export TW5_BUILD_DETAILS="Built from branch '$TRAVIS_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')"
- export TW5_BUILD_MAIN_EDITION='./editions/tw5.com'
- export TW5_BUILD_OUTPUT='./output'
- ./bin/build-site.sh
- ./bin/travis-push.sh
+354 -276
View File
@@ -1,6 +1,6 @@
#!/bin/bash
# Build all tiddlywiki.com assets
# Build all tiddlywiki.com assets.
# Default to the current version number for building the plugin library
@@ -8,18 +8,38 @@ if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.1.19
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
# Default to using tw5.com as the main edition for /index.html
if [ -z "$TW5_BUILD_MAIN_EDITION" ]; then
TW5_BUILD_MAIN_EDITION=./editions/tw5.com
fi
echo "Using TW5_BUILD_MAIN_EDITION as [$TW5_BUILD_MAIN_EDITION]"
# Default to the version of TiddlyWiki installed in this repo
if [ -z "$TW5_BUILD_TIDDLYWIKI" ]; then
TW5_BUILD_TIDDLYWIKI=./tiddlywiki.js
fi
echo "Using TW5_BUILD_TIDDLYWIKI as [$TW5_BUILD_TIDDLYWIKI]"
# Set up the build details
if [ -z "$TW5_BUILD_DETAILS" ]; then
TW5_BUILD_DETAILS="$(git symbolic-ref --short HEAD)-$(git rev-parse HEAD) from $(git remote get-url origin)"
fi
echo "Using TW5_BUILD_DETAILS as [$TW5_BUILD_DETAILS]"
if [ -z "$TW5_BUILD_COMMIT" ]; then
TW5_BUILD_COMMIT="$(git rev-parse HEAD)"
fi
echo "Using TW5_BUILD_COMMIT as [$TW5_BUILD_COMMIT]"
# Set up the build output directory
if [ -z "$TW5_BUILD_OUTPUT" ]; then
@@ -35,6 +55,8 @@ fi
echo "Using TW5_BUILD_OUTPUT as [$TW5_BUILD_OUTPUT]"
echo "Build details: $TW5_BUILD_DETAILS"
# Make the CNAME file that GitHub Pages requires
echo "tiddlywiki.com" > $TW5_BUILD_OUTPUT/CNAME
@@ -56,316 +78,372 @@ echo "<a href='./plugins/tiddlywiki/highlight/index.html'>Moved to http://tiddly
echo "<a href='./plugins/tiddlywiki/markdown/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/markdown/index.html</a>" > $TW5_BUILD_OUTPUT/markdowndemo.html
echo "<a href='./plugins/tiddlywiki/tahoelafs/index.html'>Moved to http://tiddlywiki.com/plugins/tiddlywiki/tahoelafs/index.html</a>" > $TW5_BUILD_OUTPUT/tahoelafs.html
# ######################################################
# #
# # Core distribution
# #
# ######################################################
# Put the build details into a .tid file so that it can be included in each build (deleted at the end of this script)
# # /index.html Main site
# # /favicon.ico Favicon for main site
# # /static.html Static rendering of default tiddlers
# # /alltiddlers.html Static rendering of all tiddlers
# # /static/* Static single tiddlers
# # /static/static.css Static stylesheet
# # /static/favicon.ico Favicon for static pages
# node $TW5_BUILD_TIDDLYWIKI \
# $TW5_BUILD_MAIN_EDITION \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --build favicon static index \
# || exit 1
echo -e -n "title: $:/build\ncommit: $TW5_BUILD_COMMIT\n\n$TW5_BUILD_DETAILS\n" > $TW5_BUILD_OUTPUT/build.tid
# # /empty.html Empty
# # /empty.hta For Internet Explorer
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/empty \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --build empty \
# || exit 1
######################################################
#
# Core distribution
#
######################################################
# # /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 \
# ../TiddlyWiki5/editions/dev \
# --verbose \
# --output $TW5_BUILD_OUTPUT/dev \
# --build index favicon static \
# || exit 1
# /index.html Main site
# /favicon.ico Favicon for main site
# /static.html Static rendering of default tiddlers
# /alltiddlers.html Static rendering of all tiddlers
# /static/* Static single tiddlers
# /static/static.css Static stylesheet
# /static/favicon.ico Favicon for static pages
node $TW5_BUILD_TIDDLYWIKI \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--version \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build favicon static index \
|| exit 1
# # /upgrade.html Custom edition for performing upgrades
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/upgrade \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --build upgrade \
# || exit 1
# # /encrypted.html Copy of the main file encrypted with the password "password"
# node $TW5_BUILD_TIDDLYWIKI \
# $TW5_BUILD_MAIN_EDITION \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --build encrypted \
# || exit 1
# /empty.html Empty
# /empty.hta For Internet Explorer
node $TW5_BUILD_TIDDLYWIKI \
./editions/empty \
--verbose \
--output $TW5_BUILD_OUTPUT \
--build empty \
|| exit 1
# ######################################################
# #
# # Editions
# #
# ######################################################
# /test.html Test edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/test \
--verbose \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all test.html text/plain \
|| exit 1
# # /editions/xlsx-utils/index.html xlsx-utils edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/xlsx-utils \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/xlsx-utils/ \
# --build index \
# || 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
# # /editions/resumebuilder/index.html Resume builder edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/resumebuilder \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/resumebuilder/ \
# --build index \
# || exit 1
# /upgrade.html Custom edition for performing upgrades
node $TW5_BUILD_TIDDLYWIKI \
./editions/upgrade \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build upgrade \
|| exit 1
# # /editions/text-slicer/index.html Text slicer edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/text-slicer \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/text-slicer/ \
# --build index \
# || exit 1
# /encrypted.html Copy of the main file encrypted with the password "password"
node $TW5_BUILD_TIDDLYWIKI \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--build encrypted \
|| exit 1
# # /editions/translators/index.html Translators edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/translators \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/translators/ \
# --build index \
# || exit 1
# # /editions/introduction/index.html Introduction edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/introduction \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/introduction/ \
# --build index \
# || exit 1
######################################################
#
# Editions
#
######################################################
# # /editions/full/index.html Full edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/full \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/full/ \
# --build index \
# || exit 1
# /editions/xlsx-utils/index.html xlsx-utils edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/xlsx-utils \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/xlsx-utils/ \
--build index \
|| exit 1
# # /editions/tw5.com-docs/index.html tiddlywiki.com docs edition
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/tw5.com-docs \
# --verbose \
# --output $TW5_BUILD_OUTPUT/editions/tw5.com-docs/ \
# --build index \
# || exit 1
# /editions/resumebuilder/index.html Resume builder edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/resumebuilder \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/resumebuilder/ \
--build index \
|| exit 1
# ######################################################
# #
# # Plugin demos
# #
# ######################################################
# /editions/text-slicer/index.html Text slicer edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/text-slicer \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/text-slicer/ \
--build index \
|| exit 1
# # /plugins/tiddlywiki/dynaview/index.html Demo wiki with DynaView plugin
# # /plugins/tiddlywiki/dynaview/empty.html Empty wiki with DynaView plugin
# /editions/translators/index.html Translators edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/translators \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/translators/ \
--build index \
|| exit 1
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/dynaviewdemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/dynaview/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/dynaview/empty.html text/plain \
# || exit 1
# /editions/introduction/index.html Introduction edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/introduction \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/introduction/ \
--build index \
|| exit 1
# # /plugins/tiddlywiki/katex/index.html Demo wiki with KaTeX plugin
# # /plugins/tiddlywiki/katex/empty.html Empty wiki with KaTeX plugin
# /editions/full/index.html Full edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/full \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/full/ \
--build index \
|| exit 1
# # TODO: Build the static file with the release of 5.1.3
# # --rendertiddler $:/core/templates/static.template.html plugins/tiddlywiki/katex/static.html text/plain \
# /editions/tw5.com-docs/index.html tiddlywiki.com docs edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/tw5.com-docs \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/tw5.com-docs/ \
--build index \
|| exit 1
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/katexdemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/katex/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
# || exit 1
######################################################
#
# Plugin demos
#
######################################################
# # /plugins/tiddlywiki/tahoelafs/index.html Demo wiki with Tahoe-LAFS plugin
# # /plugins/tiddlywiki/tahoelafs/empty.html Empty wiki with Tahoe-LAFS plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/tahoelafs \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/tahoelafs/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/tahoelafs/empty.html text/plain \
# || exit 1
# /plugins/tiddlywiki/innerwiki/index.html Demo wiki with Innerwiki plugin
# # /plugins/tiddlywiki/d3/index.html Demo wiki with D3 plugin
# # /plugins/tiddlywiki/d3/empty.html Empty wiki with D3 plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/d3demo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/d3/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/d3/empty.html text/plain \
# || exit 1
node $TW5_BUILD_TIDDLYWIKI \
./editions/innerwikidemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/innerwiki/index.html text/plain \
|| exit 1
# # /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
# # /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/codemirrordemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/codemirror/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/codemirror/empty.html text/plain \
# || exit 1
# /plugins/tiddlywiki/dynaview/index.html Demo wiki with DynaView plugin
# /plugins/tiddlywiki/dynaview/empty.html Empty wiki with DynaView plugin
# # /plugins/tiddlywiki/markdown/index.html Demo wiki with Markdown plugin
# # /plugins/tiddlywiki/markdown/empty.html Empty wiki with Markdown plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/markdowndemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/markdown/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/markdown/empty.html text/plain \
# || exit 1
node $TW5_BUILD_TIDDLYWIKI \
./editions/dynaviewdemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/dynaview/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/dynaview/empty.html text/plain \
|| exit 1
# # /plugins/tiddlywiki/tw2parser/index.html Demo wiki with tw2parser plugin
# # /plugins/tiddlywiki/tw2parser/empty.html Empty wiki with tw2parser plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/classicparserdemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/tw2parser/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/tw2parser/empty.html text/plain \
# || exit 1
# /plugins/tiddlywiki/katex/index.html Demo wiki with KaTeX plugin
# /plugins/tiddlywiki/katex/empty.html Empty wiki with KaTeX plugin
# # /plugins/tiddlywiki/highlight/index.html Demo wiki with highlight plugin
# # /plugins/tiddlywiki/highlight/empty.html Empty wiki with highlight plugin
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/highlightdemo \
# --verbose \
# --output $TW5_BUILD_OUTPUT \
# --rendertiddler $:/core/save/all plugins/tiddlywiki/highlight/index.html text/plain \
# --rendertiddler $:/core/save/empty plugins/tiddlywiki/highlight/empty.html text/plain \
# || exit 1
# TODO: Build the static file with the release of 5.1.3
# --rendertiddler $:/core/templates/static.template.html plugins/tiddlywiki/katex/static.html text/plain \
# ######################################################
# #
# # Language editions
# #
# ######################################################
node $TW5_BUILD_TIDDLYWIKI \
./editions/katexdemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/katex/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/katex/empty.html text/plain \
|| exit 1
# # Delete any existing static content
# /plugins/tiddlywiki/tahoelafs/index.html Demo wiki with Tahoe-LAFS plugin
# /plugins/tiddlywiki/tahoelafs/empty.html Empty wiki with Tahoe-LAFS plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/tahoelafs \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/tahoelafs/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tahoelafs/empty.html text/plain \
|| exit 1
# 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/*
# /plugins/tiddlywiki/d3/index.html Demo wiki with D3 plugin
# /plugins/tiddlywiki/d3/empty.html Empty wiki with D3 plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/d3demo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/d3/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/d3/empty.html text/plain \
|| exit 1
# # /languages/de-AT/index.html Demo wiki with de-AT language
# # /languages/de-AT/empty.html Empty wiki with de-AT language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/de-AT \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/de-AT \
# --build favicon empty static index \
# || exit 1
# /plugins/tiddlywiki/codemirror/index.html Demo wiki with codemirror plugin
# /plugins/tiddlywiki/codemirror/empty.html Empty wiki with codemirror plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/codemirrordemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/codemirror/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/codemirror/empty.html text/plain \
|| exit 1
# # /languages/de-DE/index.html Demo wiki with de-DE language
# # /languages/de-DE/empty.html Empty wiki with de-DE language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/de-DE \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/de-DE \
# --build favicon empty static index \
# || exit 1
# /plugins/tiddlywiki/markdown/index.html Demo wiki with Markdown plugin
# /plugins/tiddlywiki/markdown/empty.html Empty wiki with Markdown plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/markdowndemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/markdown/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/markdown/empty.html text/plain \
|| exit 1
# # /languages/es-ES/index.html Demo wiki with es-ES language
# # /languages/es-ES/empty.html Empty wiki with es-ES language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/es-ES \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/es-ES \
# --build favicon empty static index \
# || exit 1
# /plugins/tiddlywiki/tw2parser/index.html Demo wiki with tw2parser plugin
# /plugins/tiddlywiki/tw2parser/empty.html Empty wiki with tw2parser plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/classicparserdemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/tw2parser/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/tw2parser/empty.html text/plain \
|| exit 1
# # /languages/fr-FR/index.html Demo wiki with fr-FR language
# # /languages/fr-FR/empty.html Empty wiki with fr-FR language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/fr-FR \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/fr-FR \
# --build favicon empty static index \
# || exit 1
# /plugins/tiddlywiki/highlight/index.html Demo wiki with highlight plugin
# /plugins/tiddlywiki/highlight/empty.html Empty wiki with highlight plugin
node $TW5_BUILD_TIDDLYWIKI \
./editions/highlightdemo \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all plugins/tiddlywiki/highlight/index.html text/plain \
--rendertiddler $:/core/save/empty plugins/tiddlywiki/highlight/empty.html text/plain \
|| exit 1
# # /languages/ja-JP/index.html Demo wiki with ja-JP language
# # /languages/ja-JP/empty.html Empty wiki with ja-JP language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/ja-JP \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/ja-JP \
# --build empty index \
# || exit 1
######################################################
#
# Language editions
#
######################################################
# # /languages/ko-KR/index.html Demo wiki with ko-KR language
# # /languages/ko-KR/empty.html Empty wiki with ko-KR language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/ko-KR \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/ko-KR \
# --build favicon empty static index \
# || exit 1
# Delete any existing static content
# # /languages/zh-Hans/index.html Demo wiki with zh-Hans language
# # /languages/zh-Hans/empty.html Empty wiki with zh-Hans language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/zh-Hans \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/zh-Hans \
# --build empty index \
# || exit 1
rm $TW5_BUILD_OUTPUT/languages/de-AT/static/*
rm $TW5_BUILD_OUTPUT/languages/de-DE/static/*
rm $TW5_BUILD_OUTPUT/languages/es-ES/static/*
rm $TW5_BUILD_OUTPUT/languages/fr-FR/static/*
rm $TW5_BUILD_OUTPUT/languages/ja-JP/static/*
rm $TW5_BUILD_OUTPUT/languages/ko-KR/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hans/static/*
rm $TW5_BUILD_OUTPUT/languages/zh-Hant/static/*
# # /languages/zh-Hant/index.html Demo wiki with zh-Hant language
# # /languages/zh-Hant/empty.html Empty wiki with zh-Hant language
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/zh-Hant \
# --verbose \
# --output $TW5_BUILD_OUTPUT/languages/zh-Hant \
# --build empty index \
# || exit 1
# /languages/de-AT/index.html Demo wiki with de-AT language
# /languages/de-AT/empty.html Empty wiki with de-AT language
node $TW5_BUILD_TIDDLYWIKI \
./editions/de-AT \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/de-AT \
--build favicon empty static index \
|| exit 1
# ######################################################
# #
# # Plugin library
# #
# ######################################################
# /languages/de-DE/index.html Demo wiki with de-DE language
# /languages/de-DE/empty.html Empty wiki with de-DE language
node $TW5_BUILD_TIDDLYWIKI \
./editions/de-DE \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/de-DE \
--build favicon empty static index \
|| exit 1
# node $TW5_BUILD_TIDDLYWIKI \
# ../TiddlyWiki5/editions/pluginlibrary \
# --verbose \
# --output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
# --build \
# || exit 1
# /languages/es-ES/index.html Demo wiki with es-ES language
# /languages/es-ES/empty.html Empty wiki with es-ES language
node $TW5_BUILD_TIDDLYWIKI \
./editions/es-ES \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/es-ES \
--build favicon empty static index \
|| exit 1
# /languages/fr-FR/index.html Demo wiki with fr-FR language
# /languages/fr-FR/empty.html Empty wiki with fr-FR language
node $TW5_BUILD_TIDDLYWIKI \
./editions/fr-FR \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/fr-FR \
--build favicon empty static index \
|| exit 1
# /languages/ja-JP/index.html Demo wiki with ja-JP language
# /languages/ja-JP/empty.html Empty wiki with ja-JP language
node $TW5_BUILD_TIDDLYWIKI \
./editions/ja-JP \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/ja-JP \
--build empty index \
|| exit 1
# /languages/ko-KR/index.html Demo wiki with ko-KR language
# /languages/ko-KR/empty.html Empty wiki with ko-KR language
node $TW5_BUILD_TIDDLYWIKI \
./editions/ko-KR \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/ko-KR \
--build favicon empty static index \
|| exit 1
# /languages/zh-Hans/index.html Demo wiki with zh-Hans language
# /languages/zh-Hans/empty.html Empty wiki with zh-Hans language
node $TW5_BUILD_TIDDLYWIKI \
./editions/zh-Hans \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/zh-Hans \
--build empty index \
|| exit 1
# /languages/zh-Hant/index.html Demo wiki with zh-Hant language
# /languages/zh-Hant/empty.html Empty wiki with zh-Hant language
node $TW5_BUILD_TIDDLYWIKI \
./editions/zh-Hant \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/languages/zh-Hant \
--build empty index \
|| exit 1
######################################################
#
# Plugin library
#
######################################################
node $TW5_BUILD_TIDDLYWIKI \
./editions/pluginlibrary \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
--build \
|| exit 1
# Delete the temporary build tiddler
rm $TW5_BUILD_OUTPUT/build.tid || exit 1
-15
View File
@@ -1,15 +0,0 @@
#!/bin/bash
# Deploy the output folder to github
# pushd ../jermolene.github.io
# git add --all || exit 1
# git commit -m "Updates" || exit 1
# git push origin || exit 1
# popd
echo "(Placeholdeer feploying to GitHub)"
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env node
// Extract raw version number from package.json (without the optional "-prerelease" suffix)
if(!process.env["TW5_BUILD_TIDDLYWIKI"]) {
throw "TW5_BUILD_TIDDLYWIKI environment variable not set";
}
var fs = require("fs"),
path = require("path");
var filename = path.resolve(path.dirname(process.env["TW5_BUILD_TIDDLYWIKI"]),"./package.json"),
json = JSON.parse(fs.readFileSync(filename,"utf8"));
if(!json.version) {
throw "Missing version number in package.json";
}
process.stdout.write("v" + json.version.split("-")[0]);
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
# Build readmes from corresponding tiddlers
# Default to the version of TiddlyWiki installed in this repo
if [ -z "$TW5_BUILD_TIDDLYWIKI" ]; then
TW5_BUILD_TIDDLYWIKI=./tiddlywiki.js
fi
# tw5.com readmes
node $TW5_BUILD_TIDDLYWIKI \
editions/tw5.com \
--verbose \
--output . \
--build readmes \
|| exit 1
+2 -1
View File
@@ -1,3 +1,4 @@
<h1 class="">Script Files</h1><p>The <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> repository contains several scripts in the <code>bin</code> folder that you can use to automate common tasks, or as a useful starting point for your own scripts. See <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/Scripts%2520for%2520building%2520tiddlywiki.com.html">Scripts for building tiddlywiki.com</a> for details of the scripts used to build and release <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/</a>.</p><p>All the scripts expect to be run from the root folder of the repository.</p><h2 class=""><code>serve</code>: serves tw5.com</h2><pre><code>./bin/serve.sh -h
./bin/serve.sh [edition dir] [username] [password] [host] [port]</code></pre><p>Or:</p><pre><code>./bin/serve.cmd -h
./bin/serve.cmd [edition dir] [username] [password] [host] [port]</code></pre><p>This script starts <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> running as an HTTP server, defaulting to the content from the <code>tw5.com-server</code> edition. By default, the Node.js serves on port 8080. If the optional <code>username</code> parameter is provided, it is used for signing edits. If the <code>password</code> is provided then HTTP basic authentication is used. Run the script with the <code>-h</code> parameter to see online help.</p><p>To experiment with this configuration, run the script and then visit <code>http://127.0.0.1:8080</code> in a browser.</p><p>Changes made in the browser propagate to the server over HTTP (use the browser developer console to see these requests). The server then syncs changes to the file system (and logs each change to the screen).</p><h2 class=""><code>test</code>: build and run tests</h2><p>This script runs the <code>test</code> edition of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on the server to perform the server-side tests and to build <code>test.html</code> for running the tests in the browser.</p><h2 class=""><code>lazy</code>: serves tw5.com with lazily loaded images</h2><pre><code>./bin/lazy.sh &lt;username&gt; [&lt;password&gt;]</code></pre><p>Or:</p><pre><code>./bin/lazy.cmd &lt;username&gt; [&lt;password&gt;]</code></pre><p>This script serves the <code>tw5.com-server</code> edition content with <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/LazyLoading.html">LazyLoading</a> applied to images.</p><h2 class=""><code>2bld</code>: builds <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> 2.6.5</h2><p>This script builds <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> 2.6.5 from the original source and then displays the differences between them (<code>diff</code> is used for *nix, <code>fc</code> for Windows).</p>
./bin/serve.cmd [edition dir] [username] [password] [host] [port]</code></pre><p>This script starts <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> running as an HTTP server, defaulting to the content from the <code>tw5.com-server</code> edition. By default, the Node.js serves on port 8080. If the optional <code>username</code> parameter is provided, it is used for signing edits. If the <code>password</code> is provided then HTTP basic authentication is used. Run the script with the <code>-h</code> parameter to see online help.</p><p>To experiment with this configuration, run the script and then visit <code>http://127.0.0.1:8080</code> in a browser.</p><p>Changes made in the browser propagate to the server over HTTP (use the browser developer console to see these requests). The server then syncs changes to the file system (and logs each change to the screen).</p><h2 class=""><code>test</code>: build and run tests</h2><p>This script runs the <code>test</code> edition of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on the server to perform the server-side tests and to build <code>test.html</code> for running the tests in the browser.</p><h2 class=""><code>lazy</code>: serves tw5.com with lazily loaded images</h2><pre><code>./bin/lazy.sh &lt;username&gt; [&lt;password&gt;]</code></pre><p>Or:</p><pre><code>./bin/lazy.cmd &lt;username&gt; [&lt;password&gt;]</code></pre><p>This script serves the <code>tw5.com-server</code> edition content with <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/LazyLoading.html">LazyLoading</a> applied to images.
</p>
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# Install latest current release from npm
# (we need to force because otherwise npm will refuse to install a module of the same name)
npm --force install tiddlywiki || exit 1
# Pull existing GitHub pages content
git clone --depth=1 --branch=master "https://github.com/Jermolene/jermolene.github.io.git" output
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# Push output back to GitHub
cd output || exit 1
git config --global user.email "travis@travis-ci.org" || exit 1
git config --global user.name "Travis CI" || exit 1
git add -A . || exit 1
git commit --message "Travis build: $TRAVIS_BUILD_NUMBER of $TRAVIS_BRANCH ($(date +'%F %T %Z'))" || exit 1
git remote add deploy "https://$GH_TOKEN@github.com/Jermolene/jermolene.github.io.git" &>/dev/null || exit 1
git push deploy master &>/dev/null || exit 1
cd .. || exit 1
+250 -10
View File
@@ -51,6 +51,63 @@ $tw.utils.isArray = function(value) {
return Object.prototype.toString.call(value) == "[object Array]";
};
/*
Check if an array is equal by value and by reference.
*/
$tw.utils.isArrayEqual = function(array1,array2) {
if(array1 === array2) {
return true;
}
array1 = array1 || [];
array2 = array2 || [];
if(array1.length !== array2.length) {
return false;
}
return array1.every(function(value,index) {
return value === array2[index];
});
};
/*
Push entries onto an array, removing them first if they already exist in the array
array: array to modify (assumed to be free of duplicates)
value: a single value to push or an array of values to push
*/
$tw.utils.pushTop = function(array,value) {
var t,p;
if($tw.utils.isArray(value)) {
// Remove any array entries that are duplicated in the new values
if(value.length !== 0) {
if(array.length !== 0) {
if(value.length < array.length) {
for(t=0; t<value.length; t++) {
p = array.indexOf(value[t]);
if(p !== -1) {
array.splice(p,1);
}
}
} else {
for(t=array.length-1; t>=0; t--) {
p = value.indexOf(array[t]);
if(p !== -1) {
array.splice(t,1);
}
}
}
}
// Push the values on top of the main array
array.push.apply(array,value);
}
} else {
p = array.indexOf(value);
if(p !== -1) {
array.splice(p,1);
}
array.push(value);
}
return array;
};
/*
Determine if a value is a date
*/
@@ -89,7 +146,9 @@ Helper for making DOM elements
tag: tag name
options: see below
Options include:
namespace: defaults to http://www.w3.org/1999/xhtml
attributes: hashmap of attribute values
style: hashmap of styles
text: text to add as a child node
children: array of further child nodes
innerHTML: optional HTML for element
@@ -99,7 +158,7 @@ eventListeners: array of event listeners (this option won't work until $tw.utils
*/
$tw.utils.domMaker = function(tag,options) {
var doc = options.document || document;
var element = doc.createElement(tag);
var element = doc.createElementNS(options.namespace || "http://www.w3.org/1999/xhtml",tag);
if(options["class"]) {
element.className = options["class"];
}
@@ -115,6 +174,9 @@ $tw.utils.domMaker = function(tag,options) {
$tw.utils.each(options.attributes,function(attribute,name) {
element.setAttribute(name,attribute);
});
$tw.utils.each(options.style,function(value,name) {
element.style[name] = value;
});
if(options.eventListeners) {
$tw.utils.addEventListeners(element,options.eventListeners);
}
@@ -862,6 +924,61 @@ $tw.Tiddler.prototype.hasField = function(field) {
return $tw.utils.hop(this.fields,field);
};
/*
Compare two tiddlers for equality
tiddler: the tiddler to compare
excludeFields: array of field names to exclude from the comparison
*/
$tw.Tiddler.prototype.isEqual = function(tiddler,excludeFields) {
if(!(tiddler instanceof $tw.Tiddler)) {
return false;
}
excludeFields = excludeFields || [];
var self = this,
differences = []; // Fields that have differences
// Add to the differences array
function addDifference(fieldName) {
// Check for this field being excluded
if(excludeFields.indexOf(fieldName) === -1) {
// Save the field as a difference
$tw.utils.pushTop(differences,fieldName);
}
}
// Returns true if the two values of this field are equal
function isFieldValueEqual(fieldName) {
var valueA = self.fields[fieldName],
valueB = tiddler.fields[fieldName];
// Check for identical string values
if(typeof(valueA) === "string" && typeof(valueB) === "string" && valueA === valueB) {
return true;
}
// Check for identical array values
if($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {
return true;
}
// Check for identical date values
if($tw.utils.isDate(valueA) && $tw.utils.isDate(valueB) && valueA.getTime() === valueB.getTime()) {
return true;
}
// Otherwise the fields must be different
return false;
}
// Compare our fields
for(var fieldName in this.fields) {
if(!isFieldValueEqual(fieldName)) {
addDifference(fieldName);
}
}
// There's a difference for every field in the other tiddler that we don't have
for(fieldName in tiddler.fields) {
if(!(fieldName in this.fields)) {
addDifference(fieldName);
}
}
// Return whether there were any differences
return differences.length === 0;
};
/*
Register and install the built in tiddler field modules
*/
@@ -896,7 +1013,7 @@ $tw.modules.define("$:/boot/tiddlerfields/list","tiddlerfield",{
/*
Wiki constructor. State is stored in private members that only a small number of privileged accessor methods have direct access. Methods added via the prototype have to use these accessors and cannot access the state data directly.
options include:
shadowTiddlers: Array of shadow tiddlers to be added
enableIndexers - Array of indexer names to enable, or null to use all available indexers
*/
$tw.Wiki = function(options) {
options = options || {};
@@ -911,14 +1028,31 @@ $tw.Wiki = function(options) {
},
pluginTiddlers = [], // Array of tiddlers containing registered plugins, ordered by priority
pluginInfo = Object.create(null), // Hashmap of parsed plugin content
shadowTiddlers = options.shadowTiddlers || Object.create(null), // Hashmap by title of {source:, tiddler:}
shadowTiddlers = Object.create(null), // Hashmap by title of {source:, tiddler:}
shadowTiddlerTitles = null,
getShadowTiddlerTitles = function() {
if(!shadowTiddlerTitles) {
shadowTiddlerTitles = Object.keys(shadowTiddlers);
}
return shadowTiddlerTitles;
};
},
enableIndexers = options.enableIndexers || null,
indexers = [],
indexersByName = Object.create(null);
this.addIndexer = function(indexer,name) {
// Bail if this indexer is not enabled
if(enableIndexers && enableIndexers.indexOf(name) === -1) {
return;
}
indexers.push(indexer);
indexersByName[name] = indexer;
indexer.init();
};
this.getIndexer = function(name) {
return indexersByName[name] || null;
};
// Add a tiddler to the store
this.addTiddler = function(tiddler) {
@@ -931,12 +1065,33 @@ $tw.Wiki = function(options) {
if(title) {
// Uncomment the following line for detailed logs of all tiddler writes
// console.log("Adding",title,tiddler)
// Record the old tiddler state
var updateDescriptor = {
old: {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
// Save the new tiddler
tiddlers[title] = tiddler;
// Check we've got it's title
if(tiddlerTitles && tiddlerTitles.indexOf(title) === -1) {
tiddlerTitles.push(title);
}
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: tiddler,
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.update(updateDescriptor);
});
// Queue a change event
this.enqueueTiddlerEvent(title);
}
}
@@ -947,15 +1102,36 @@ $tw.Wiki = function(options) {
// Uncomment the following line for detailed logs of all tiddler deletions
// console.log("Deleting",title)
if($tw.utils.hop(tiddlers,title)) {
// Record the old tiddler state
var updateDescriptor = {
old: {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
}
// Delete the tiddler
delete tiddlers[title];
// Delete it from the list of titles
if(tiddlerTitles) {
var index = tiddlerTitles.indexOf(title);
if(index !== -1) {
tiddlerTitles.splice(index,1);
}
}
// Record the new tiddler state
updateDescriptor["new"] = {
tiddler: this.getTiddler(title),
shadow: this.isShadowTiddler(title),
exists: this.tiddlerExists(title)
}
// Update indexes
this.clearCache(title);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.update(updateDescriptor);
});
// Queue a change event
this.enqueueTiddlerEvent(title,true);
}
};
@@ -1042,7 +1218,6 @@ $tw.Wiki = function(options) {
callback(tiddlers[title],title);
}
}
};
// Test for the existence of a tiddler (excludes shadow tiddlers)
@@ -1156,8 +1331,14 @@ $tw.Wiki = function(options) {
shadowTiddlerTitles = null;
this.clearCache(null);
this.clearGlobalCache();
$tw.utils.each(indexers,function(indexer) {
indexer.rebuild();
});
};
if(this.addIndexersToWiki) {
this.addIndexersToWiki();
}
};
// Dummy methods that will be filled in after boot
@@ -1352,8 +1533,40 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/html","tiddlerdeserializer",{
});
$tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
"application/json": function(text,fields) {
var data = JSON.parse(text);
return $tw.utils.isArray(data) ? data : [data];
var isTiddlerValid = function(data) {
// Not valid if it's not an object with a title property
if(typeof(data) !== "object" || !$tw.utils.hop(data,"title")) {
return false;
}
for(var f in data) {
if($tw.utils.hop(data,f)) {
// Check field name doesn't contain whitespace or control characters
if(typeof(data[f]) !== "string" || /[\x00-\x1F\s]/.test(f)) {
return false;
}
}
}
return true;
},
isTiddlerArrayValid = function(data) {
for(var t=0; t<data.length; t++) {
if(!isTiddlerValid(data[t])) {
return false;
}
}
return true;
},
data = JSON.parse(text);
if($tw.utils.isArray(data) && isTiddlerArrayValid(data)) {
return data;
} else if(isTiddlerValid(data)) {
return [data];
} else {
// Plain JSON file
fields.text = text;
fields.type = "application/json";
return [fields];
}
}
});
@@ -1506,9 +1719,11 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
typeInfo = type ? $tw.config.contentTypeInfo[type] : null,
data = fs.readFileSync(filepath,typeInfo ? typeInfo.encoding : "utf8"),
tiddlers = $tw.wiki.deserializeTiddlers(ext,data,fields),
metadata;
if(ext !== ".json" && tiddlers.length === 1) {
metadata = $tw.loadMetadataForFile(filepath);
if(metadata) {
if(type === "application/json") {
tiddlers = [{text: data, type: "application/json"}];
}
tiddlers = [$tw.utils.extend({},tiddlers[0],metadata)];
}
return {filepath: filepath, type: type, tiddlers: tiddlers, hasMetaFile: !!metadata};
@@ -1738,8 +1953,10 @@ $tw.loadPlugin = function(name,paths) {
var pluginFields = $tw.loadPluginFolder(pluginPath);
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
return;
}
}
console.log("Warning: Cannot find plugin '" + name + "'");
};
/*
@@ -1753,7 +1970,7 @@ $tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
if(env) {
env.split(path.delimiter).map(function(item) {
if(item) {
pluginPaths.push(item)
pluginPaths.push(item);
}
});
}
@@ -1889,6 +2106,21 @@ $tw.loadTiddlersNode = function() {
});
// Load the core tiddlers
$tw.wiki.addTiddler($tw.loadPluginFolder($tw.boot.corePath));
// Load any extra plugins
$tw.utils.each($tw.boot.extraPlugins,function(name) {
if(name.charAt(0) === "+") { // Relative path to plugin
var pluginFields = $tw.loadPluginFolder(name.substring(1));;
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
} else {
var parts = name.split("/"),
type = parts[0];
if(parts.length === 3 && ["plugins","themes","languages"].indexOf(type) !== -1) {
$tw.loadPlugins([parts[1] + "/" + parts[2]],$tw.config[type + "Path"],$tw.config[type + "EnvVar"]);
}
}
});
// Load the tiddlers from the wiki directory
if($tw.boot.wikiPath) {
$tw.boot.wikiInfo = $tw.loadWikiTiddlers($tw.boot.wikiPath);
@@ -1952,6 +2184,12 @@ $tw.boot.startup = function(options) {
if($tw.boot.argv.length === 0) {
$tw.boot.argv = ["--help"];
}
// Parse any extra plugin references
$tw.boot.extraPlugins = $tw.boot.extraPlugins || [];
while($tw.boot.argv[0] && $tw.boot.argv[0].indexOf("+") === 0) {
$tw.boot.extraPlugins.push($tw.boot.argv[0].substring(1));
$tw.boot.argv.splice(0,1);
}
// If the first command line argument doesn't start with `--` then we
// interpret it as the path to the wiki folder, which will otherwise default
// to the current folder
@@ -2037,6 +2275,8 @@ $tw.boot.startup = function(options) {
if($tw.preloadTiddlers) {
$tw.wiki.addTiddlers($tw.preloadTiddlers);
}
// Give hooks a chance to modify the store
$tw.hooks.invokeHook("th-boot-tiddlers-loaded");
// Unpack plugin tiddlers
$tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin",$tw.safeMode ? ["$:/core"] : undefined);
+1 -2
View File
@@ -1,4 +1,3 @@
<h1 class="">Contributing to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></h1><p>We welcome contributions to the code and documentation of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> in several ways:</p><ul><li><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/ReportingBugs.html">ReportingBugs</a></li><li>Helping to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Improving%2520TiddlyWiki%2520Documentation.html">improve our documentation</a></li><li>Contributing to the code via <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5" rel="noopener noreferrer" target="_blank">GitHub</a><ul><li>See <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/dev</a> for more details</li></ul></li></ul><p>There are other ways to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/HelpingTiddlyWiki.html">help TiddlyWiki</a> too.</p><h1 class="">Contributor License Agreement</h1><p>Like other <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/OpenSource.html">OpenSource</a> projects, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/UnaMesa.html">UnaMesa</a> Association (the legal entity that owns <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on behalf of the community).</p><ul><li>For individuals use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a></li><li>For entities use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a></li></ul><h1 class="">How to sign the CLA</h1><p>Create a <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/GitHub.html">GitHub</a> pull request to add your name to <code>cla-individual.md</code> or <code>cla-entity.md</code>, with the date in the format (YYYY/MM/DD).</p><p><strong>step by step</strong></p><ol><li>Navigate to <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a> or <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a> according to whether you are signing as an individual or representative of an organisation</li><li>Click the &quot;edit&quot; button at the top-right corner (clicking this button will fork the project so you can edit the file)</li><li>Add your name at the bottom<ul><li>eg: <code>Jeremy Ruston, @Jermolene, 2011/11/22</code></li></ul></li><li>Below the edit box for the CLA text you should see a box labelled <strong>Propose file change</strong></li><li>Enter a brief title to explain the change (eg, &quot;Signing the CLA&quot;)</li><li>Click the green button labelled <strong>Propose file change</strong></li><li>On the following screen, click the green button labelled <strong>Create pull request</strong></li></ol><hr><p><em>The CLA documents used for this project were created using <a class="tc-tiddlylink-external" href="http://www.harmonyagreements.org" rel="noopener noreferrer" target="_blank">Harmony Project Templates</a>. &quot;HA-CLA-I-LIST Version 1.0&quot; for &quot;CLA-individual&quot; and &quot;HA-CLA-E-LIST Version 1.0&quot; for &quot;CLA-entity&quot;.</em></p><p>Remarks
----—</p><ul><li><ul><li>When not owning the copyright in the entire work of authorship**</li></ul></li></ul><p>In this case, please clearly state so, since otherwise we assume that you are the legal copyright holder of the contributed work! Please provide links and additional information that clarify under which license the rest of the code is distributed.
<h1 class="">Contributing to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></h1><p>We welcome contributions to the code and documentation of <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> in several ways:</p><ul><li><a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/ReportingBugs.html">ReportingBugs</a></li><li>Helping to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/Improving%2520TiddlyWiki%2520Documentation.html">improve our documentation</a></li><li>Contributing to the code via <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5" rel="noopener noreferrer" target="_blank">GitHub</a><ul><li>See <a class="tc-tiddlylink-external" href="https://tiddlywiki.com/dev" rel="noopener noreferrer" target="_blank">https://tiddlywiki.com/dev</a> for more details</li></ul></li></ul><p>There are other ways to <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/HelpingTiddlyWiki.html">help TiddlyWiki</a> too.</p><h1 class="">Contributor License Agreement</h1><p>Like other <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/OpenSource.html">OpenSource</a> projects, <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a> needs a signed contributor license agreement from individual contributors. This is a legal agreement that allows contributors to assert that they own the copyright of their contribution, and that they agree to license it to the <a class="tc-tiddlylink tc-tiddlylink-missing" href="https://tiddlywiki.com/static/UnaMesa.html">UnaMesa</a> Association (the legal entity that owns <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki.html">TiddlyWiki</a> on behalf of the community).</p><ul><li>For individuals use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a></li><li>For entities use: <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a></li></ul><h1 class="">How to sign the CLA</h1><p>Create a <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/GitHub.html">GitHub</a> pull request to add your name to <code>cla-individual.md</code> or <code>cla-entity.md</code>, with the date in the format (YYYY/MM/DD).</p><p><strong>step by step</strong></p><ol><li>Navigate to <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-individual.md" rel="noopener noreferrer" target="_blank">licenses/CLA-individual</a> or <a class="tc-tiddlylink-external" href="https://github.com/Jermolene/TiddlyWiki5/tree/master/licenses/cla-entity.md" rel="noopener noreferrer" target="_blank">licenses/CLA-entity</a> according to whether you are signing as an individual or representative of an organisation</li><li>Ensure that the &quot;branch&quot; dropdown at the top left is set to <code>tiddlywiki-com</code></li><li>Click the &quot;edit&quot; button at the top-right corner (clicking this button will fork the project so you can edit the file)</li><li>Add your name at the bottom<ul><li>eg: <code>Jeremy Ruston, @Jermolene, 2011/11/22</code></li></ul></li><li>Below the edit box for the CLA text you should see a box labelled <strong>Propose file change</strong></li><li>Enter a brief title to explain the change (eg, &quot;Signing the CLA&quot;)</li><li>Click the green button labelled <strong>Propose file change</strong></li><li>On the following screen, click the green button labelled <strong>Create pull request</strong></li></ol><hr><p><em>The CLA documents used for this project were created using <a class="tc-tiddlylink-external" href="http://www.harmonyagreements.org" rel="noopener noreferrer" target="_blank">Harmony Project Templates</a>. &quot;HA-CLA-I-LIST Version 1.0&quot; for &quot;CLA-individual&quot; and &quot;HA-CLA-E-LIST Version 1.0&quot; for &quot;CLA-entity&quot;.</em></p><h2 class="">Remarks</h2><p><strong>If you do not own the copyright in the entire work of authorship</strong>:</p><p>In this case, please clearly state so and provide links and any additional information that clarify under which license the rest of the code is distributed.
</p><p><em>This file was automatically generated by <a class="tc-tiddlylink tc-tiddlylink-resolves" href="https://tiddlywiki.com/static/TiddlyWiki5.html">TiddlyWiki5</a></em>
</p>
+2
View File
@@ -32,6 +32,7 @@ ExportTiddler/Caption: export tiddler
ExportTiddler/Hint: Export tiddler
ExportTiddlers/Caption: export tiddlers
ExportTiddlers/Hint: Export tiddlers
SidebarSearch/Hint: Select the sidebar search field
Fold/Caption: fold tiddler
Fold/Hint: Fold the body of this tiddler
Fold/FoldBar/Caption: fold-bar
@@ -181,6 +182,7 @@ Subscript/Caption: subscript
Subscript/Hint: Apply subscript formatting to selection
Superscript/Caption: superscript
Superscript/Hint: Apply superscript formatting to selection
ToggleSidebar/Hint: Toggle the sidebar visibility
Transcludify/Caption: transclusion
Transcludify/Hint: Wrap selection in curly brackets
Underline/Caption: underline
+14
View File
@@ -47,6 +47,8 @@ LoadedModules/Hint: These are the currently loaded tiddler modules linked to the
Palette/Caption: Palette
Palette/Editor/Clone/Caption: clone
Palette/Editor/Clone/Prompt: It is recommended that you clone this shadow palette before editing it
Palette/Editor/Delete/Hint: delete this entry from the current palette
Palette/Editor/Names/External/Show: Show color names that are not part of the current palette
Palette/Editor/Prompt/Modified: This shadow palette has been modified
Palette/Editor/Prompt: Editing
Palette/Editor/Reset/Caption: reset
@@ -89,6 +91,18 @@ Saving/DownloadSaver/Hint: These settings apply to the HTML5-compatible download
Saving/General/Caption: General
Saving/General/Hint: These settings apply to all the loaded savers
Saving/Hint: Settings used for saving the entire TiddlyWiki as a single file via a saver module
Saving/GitService/Branch: Target branch for saving
Saving/GitService/CommitMessage: Saved by TiddlyWiki
Saving/GitService/Description: These settings are only used when saving to <<service-name>>
Saving/GitService/Filename: Filename of target file (e.g. `index.html`)
Saving/GitService/Path: Path to target file (e.g. `/wiki/`)
Saving/GitService/Repo: Target repository (e.g. `Jermolene/TiddlyWiki5`)
Saving/GitService/ServerURL: Server API URL
Saving/GitService/UserName: Username
Saving/GitService/GitHub/Caption: ~GitHub Saver
Saving/GitService/GitHub/Password: Password, OAUTH token, or personal access token (see [[GitHub help page|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]] for details)
Saving/GitService/GitLab/Caption: ~GitLab Saver
Saving/GitService/GitLab/Password: Personal access token for API (see [[GitLab help page|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html for details]] for details)
Saving/TiddlySpot/Advanced/Heading: Advanced Settings
Saving/TiddlySpot/BackupDir: Backup Directory
Saving/TiddlySpot/Backups: Backups
+3 -1
View File
@@ -14,8 +14,9 @@ draft.of: For draft tiddlers, contains the title of the tiddler of which this is
draft.title: For draft tiddlers, contains the proposed new title of the tiddler
footer: The footer text for a wizard
hack-to-give-us-something-to-compare-against: A temporary storage field used in [[$:/core/templates/static.content]]
hide-body: The view template will hide bodies of tiddlers if set to: ''yes''
icon: The title of the tiddler containing the icon associated with a tiddler
library: If set to "yes" indicates that a tiddler should be saved as a JavaScript library
library: Indicates that a tiddler should be saved as a JavaScript library if set to: ''yes''
list: An ordered list of tiddler titles associated with a tiddler
list-before: If set, the title of a tiddler before which this tiddler should be added to the ordered list of tiddler titles, or at the start of the list if this field is present but empty
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
@@ -31,5 +32,6 @@ subtitle: The subtitle text for a wizard
tags: A list of tags associated with a tiddler
text: The body text of a tiddler
title: The unique name of a tiddler
toc-link: Suppresses the tiddler's link in a Table of Contents tree if set to: ''no''
type: The content type of a tiddler
version: Version information for a plugin
+1
View File
@@ -10,6 +10,7 @@ Orphans: Orphan tiddlers
SystemTiddlers: System tiddlers
ShadowTiddlers: Shadow tiddlers
OverriddenShadowTiddlers: Overridden shadow tiddlers
SessionTiddlers: Tiddlers modified since the wiki was loaded
SystemTags: System tags
StoryList: Tiddlers in the story river, excluding <$text text="$:/AdvancedSearch"/>
TypedTiddlers: Non wiki-text tiddlers
@@ -0,0 +1,8 @@
title: $:/language/Help/deletetiddlers
description: Deletes a group of tiddlers
<<.from-version "5.1.20">> Deletes a group of tiddlers identified by a filter.
```
--deletetiddlers <filter>
```
+1
View File
@@ -28,6 +28,7 @@ All parameters are optional with safe defaults, and can be specified in any orde
* ''tls-cert'' - pathname of TLS certificate file (relative to wiki folder)
* ''tls-key'' - pathname of TLS key file (relative to wiki folder)
* ''debug-level'' - optional debug level; set to "debug" to view request details (defaults to "none")
* ''gzip'' - set to "yes" to enable gzip compression for some http endpoints (defaults to "no")
For information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.
+4 -2
View File
@@ -4,10 +4,12 @@ description: Load tiddlers from a file
Load tiddlers from TiddlyWiki (`.html`), `.tiddler`, `.tid`, `.json` or other local files. The processing applied to incoming files is determined by the file extension. Use the alternative `import` command if you need to specify the deserializer and encoding explicitly.
```
--load <filepath>
--load <dirpath>
--load <filepath> [noerror]
--load <dirpath> [noerror]
```
By default, the load command raises an error if no tiddlers are found. The error can be suppressed by providing the optional "noerror" parameter.
To load tiddlers from an encrypted TiddlyWiki file you should first specify the password with the PasswordCommand. For example:
```
+1 -1
View File
@@ -13,8 +13,8 @@ A name and value for an additional variable may optionally also be specified.
* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered
* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename
* ''template'': Optional template through which each tiddler is rendered
* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)
* ''template'': Optional template through which each tiddler is rendered
* ''name'': Name of optional variable
* ''value'': Value of optional variable
@@ -0,0 +1,19 @@
title: $:/language/Help/savewikifolder
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 <wikifolderpath> [<filter>]
```
* The target wiki folder must be empty or non-existent
* The filter specifies which tiddlers should be included. It is optional, defaulting to `[all[tiddlers]]`
* 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
A common usage is to convert a TiddlyWiki HTML file into a wiki folder:
```
tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder
```
+2
View File
@@ -18,4 +18,6 @@ Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>
Upgrader/State/Suppressed: Blocked temporary state tiddler
Upgrader/System/Suppressed: Blocked system tiddler
Upgrader/System/Warning: Core module tiddler
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>
+42
View File
@@ -0,0 +1,42 @@
/*\
title: $:/core/modules/commands/deletetiddlers.js
type: application/javascript
module-type: command
Command to delete tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "deletetiddlers",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filter";
}
var self = this,
wiki = this.commander.wiki,
filter = this.params[0],
tiddlers = wiki.filterTiddlers(filter);
$tw.utils.each(tiddlers,function(title) {
wiki.deleteTiddler(title);
});
return null;
};
exports.Command = Command;
})();
+1 -1
View File
@@ -38,7 +38,7 @@ Command.prototype.execute = function() {
count++;
});
});
if(!count) {
if(!count && self.params[1] !== "noerror") {
self.callback("No tiddlers found in file \"" + self.params[0] + "\"");
} else {
self.callback(null);
+184
View File
@@ -0,0 +1,184 @@
/*\
title: $:/core/modules/commands/savewikifolder.js
type: application/javascript
module-type: command
Command to save the current wiki as a wiki folder
--savewikifolder <wikifolderpath> [<filter>]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "savewikifolder",
synchronous: true
};
var fs,path;
if($tw.node) {
fs = require("fs");
path = require("path");
}
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing wiki folder path";
}
var wikifoldermaker = new WikiFolderMaker(this.params[0],this.params[1],this.commander);
return wikifoldermaker.save();
};
function WikiFolderMaker(wikiFolderPath,wikiFilter,commander) {
this.wikiFolderPath = wikiFolderPath;
this.wikiFilter = wikiFilter || "[all[tiddlers]]";
this.commander = commander;
this.wiki = commander.wiki;
this.savedPaths = []; // So that we can detect filename clashes
}
WikiFolderMaker.prototype.log = function(str) {
if(this.commander.verbose) {
console.log(str);
}
};
WikiFolderMaker.prototype.tiddlersToIgnore = [
"$:/boot/boot.css",
"$:/boot/boot.js",
"$:/boot/bootprefix.js",
"$:/core",
"$:/library/sjcl.js",
"$:/temp/info-plugin"
];
/*
Returns null if successful, or an error string if there was an error
*/
WikiFolderMaker.prototype.save = function() {
var self = this;
// Check that the output directory doesn't exist
if(fs.existsSync(this.wikiFolderPath) && !$tw.utils.isDirectoryEmpty(this.wikiFolderPath)) {
return "The unpackwiki command requires that the output wiki folder be empty";
}
// Get the tiddlers from the source wiki
var tiddlerTitles = this.wiki.filterTiddlers(this.wikiFilter);
// Initialise a new tiddlwiki.info file
var newWikiInfo = {};
// Process each incoming tiddler in turn
$tw.utils.each(tiddlerTitles,function(title) {
var tiddler = self.wiki.getTiddler(title);
if(tiddler) {
if(self.tiddlersToIgnore.indexOf(title) !== -1) {
// Ignore the core plugin and the ephemeral info plugin
self.log("Ignoring tiddler: " + title);
} else {
var type = tiddler.fields.type,
pluginType = tiddler.fields["plugin-type"];
if(type === "application/json" && pluginType) {
// Plugin tiddler
var libraryDetails = self.findPluginInLibrary(title);
if(libraryDetails) {
// A plugin from the core library
self.log("Adding built-in plugin: " + libraryDetails.name);
newWikiInfo[libraryDetails.type] = newWikiInfo[libraryDetails.type] || [];
$tw.utils.pushTop(newWikiInfo[libraryDetails.type],libraryDetails.name);
} else {
// A custom plugin
self.log("Processing custom plugin: " + title);
self.saveCustomPlugin(tiddler);
}
} else {
// Ordinary tiddler
self.saveTiddler("tiddlers",tiddler);
}
}
}
});
// Save the tiddlywiki.info file
this.saveJSONFile("tiddlywiki.info",newWikiInfo);
self.log("Writing tiddlywiki.info: " + JSON.stringify(newWikiInfo,null,$tw.config.preferences.jsonSpaces));
return null;
};
/*
Test whether the specified tiddler is a plugin in the plugin library
*/
WikiFolderMaker.prototype.findPluginInLibrary = function(title) {
var parts = title.split("/"),
pluginPath, type, name;
if(parts[0] === "$:") {
if(parts[1] === "languages" && parts.length === 3) {
pluginPath = "languages" + path.sep + parts[2];
type = parts[1];
name = parts[2];
} else if(parts[1] === "plugins" || parts[1] === "themes" && parts.length === 4) {
pluginPath = parts[1] + path.sep + parts[2] + path.sep + parts[3];
type = parts[1];
name = parts[2] + "/" + parts[3];
}
}
if(pluginPath && type && name) {
pluginPath = path.resolve($tw.boot.bootPath,"..",pluginPath);
if(fs.existsSync(pluginPath)) {
return {
pluginPath: pluginPath,
type: type,
name: name
};
}
}
return false;
};
WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
var self = this,
pluginTitle = pluginTiddler.fields.title,
titleParts = pluginTitle.split("/"),
directory = $tw.utils.generateTiddlerFilepath(titleParts[titleParts.length - 1],{
directory: path.resolve(this.wikiFolderPath,pluginTiddler.fields["plugin-type"] + "s")
}),
pluginInfo = pluginTiddler.getFieldStrings({exclude: ["text","type"]});
this.saveJSONFile(directory + path.sep + "plugin.info",pluginInfo);
self.log("Writing " + directory + path.sep + "plugin.info: " + JSON.stringify(pluginInfo,null,$tw.config.preferences.jsonSpaces));
var pluginTiddlers = JSON.parse(pluginTiddler.fields.text).tiddlers; // A hashmap of tiddlers in the plugin
$tw.utils.each(pluginTiddlers,function(tiddler) {
self.saveTiddler(directory,new $tw.Tiddler(tiddler));
});
};
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: path.resolve(this.wikiFolderPath,directory),
wiki: this.wiki
});
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
};
WikiFolderMaker.prototype.saveJSONFile = function(filename,json) {
this.saveTextFile(filename,JSON.stringify(json,null,$tw.config.preferences.jsonSpaces));
};
WikiFolderMaker.prototype.saveTextFile = function(filename,data) {
this.saveFile(filename,"utf8",data);
};
WikiFolderMaker.prototype.saveFile = function(filename,encoding,data) {
var filepath = path.resolve(this.wikiFolderPath,filename);
$tw.utils.createFileDirectories(filepath);
fs.writeFileSync(filepath,data,encoding);
};
exports.Command = Command;
})();
+14
View File
@@ -42,6 +42,7 @@ function FramedEngine(options) {
this.iframeNode.style.border = "none";
this.iframeNode.style.padding = "0";
this.iframeNode.style.resize = "none";
this.iframeNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
this.iframeDoc.body.style.margin = "0";
this.iframeDoc.body.style.padding = "0";
this.widget.domNodes.push(this.iframeNode);
@@ -70,11 +71,15 @@ function FramedEngine(options) {
if(this.widget.editRows) {
this.domNode.setAttribute("rows",this.widget.editRows);
}
if(this.widget.editTabIndex) {
this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex);
}
// Copy the styles from the dummy textarea
this.copyStyles();
// Add event listeners
$tw.utils.addEventListeners(this.domNode,[
{name: "click",handlerObject: this,handlerMethod: "handleClickEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"},
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"}
]);
@@ -92,6 +97,7 @@ FramedEngine.prototype.copyStyles = function() {
this.domNode.style.display = "block";
this.domNode.style.width = "100%";
this.domNode.style.margin = "0";
this.domNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background");
// In Chrome setting -webkit-text-fill-color overrides the placeholder text colour
this.domNode.style["-webkit-text-fill-color"] = "currentcolor";
};
@@ -147,6 +153,14 @@ FramedEngine.prototype.focus = function() {
this.domNode.select();
}
};
/*
Handle the focus event
*/
FramedEngine.prototype.handleFocusEvent = function(event) {
this.widget.cancelPopups();
return true;
};
/*
Handle a click
+4
View File
@@ -49,6 +49,9 @@ function SimpleEngine(options) {
if(this.widget.editClass) {
this.domNode.className = this.widget.editClass;
}
if(this.widget.editTabIndex) {
this.domNode.setAttribute("tabindex",this.widget.editTabIndex);
}
// Add an input event handler
$tw.utils.addEventListeners(this.domNode,[
{name: "focus", handlerObject: this, handlerMethod: "handleFocusEvent"},
@@ -119,6 +122,7 @@ SimpleEngine.prototype.handleInputEvent = function(event) {
Handle a dom "focus" event
*/
SimpleEngine.prototype.handleFocusEvent = function(event) {
this.widget.cancelPopups();
if(this.widget.editFocusPopup) {
$tw.popup.triggerPopup({
domNode: this.domNode,
+12 -4
View File
@@ -176,6 +176,7 @@ 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.editTabIndex = this.getAttribute("tabindex");
// Get the default editor element tag and type
var tag,type;
if(this.editField === "text") {
@@ -192,7 +193,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
type = type || "text";
}
// Get the rest of our parameters
this.editTag = this.getAttribute("tag",tag);
this.editTag = this.getAttribute("tag",tag) || "input";
this.editType = this.getAttribute("type",type);
// Make the child widgets
this.makeChildWidgets();
@@ -207,7 +208,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 || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) {
this.refreshSelf();
return true;
} else if(changedTiddlers[this.editTitle]) {
@@ -216,7 +217,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
this.engine.fixHeight();
if(this.editShowToolbar) {
return this.refreshChildren(changedTiddlers);
return this.refreshChildren(changedTiddlers);
} else {
return false;
}
@@ -247,6 +248,13 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
}
};
/*
Cancel Popups
*/
EditTextWidget.prototype.cancelPopups = function() {
$tw.popup.cancel(0,this.engine.domNode);
};
/*
Handle a dom "keydown" event, which we'll bubble up to our container for the keyboard widgets benefit
*/
@@ -266,7 +274,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
el.dispatchEvent(clickEvent);
event.preventDefault();
event.stopPropagation();
return true;
return true;
}
}
}
@@ -16,14 +16,12 @@ exports["wrap-selection"] = function(event,operation) {
if(operation.selStart === operation.selEnd) {
// No selection; check if we're within the prefix/suffix
if(operation.text.substring(operation.selStart - event.paramObject.prefix.length,operation.selStart + event.paramObject.suffix.length) === event.paramObject.prefix + event.paramObject.suffix) {
// Remove the prefix and suffix unless they comprise the entire text
if(operation.selStart > event.paramObject.prefix.length || (operation.selEnd + event.paramObject.suffix.length) < operation.text.length ) {
operation.cutStart = operation.selStart - event.paramObject.prefix.length;
operation.cutEnd = operation.selEnd + event.paramObject.suffix.length;
operation.replacement = "";
operation.newSelStart = operation.cutStart;
operation.newSelEnd = operation.newSelStart;
}
// Remove the prefix and suffix
operation.cutStart = operation.selStart - event.paramObject.prefix.length;
operation.cutEnd = operation.selEnd + event.paramObject.suffix.length;
operation.replacement = "";
operation.newSelStart = operation.cutStart;
operation.newSelEnd = operation.newSelStart;
} else {
// Wrap the cursor instead
operation.cutStart = operation.selStart;
+6 -2
View File
@@ -119,7 +119,7 @@ exports.parseFilter = function(filterString) {
p = 0, // Current position in the filter string
match;
var whitespaceRegExp = /(\s+)/mg,
operandRegExp = /((?:\+|\-|~)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
operandRegExp = /((?:\+|\-|~|=)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -248,6 +248,10 @@ exports.compileFilter = function(filterString) {
return function(results,source,widget) {
$tw.utils.pushTop(results,operationSubFunction(source,widget));
};
case "=": // The results of the operation are pushed into the result without deduplication
return function(results,source,widget) {
Array.prototype.push.apply(results,operationSubFunction(source,widget));
};
case "-": // The results of this operation are removed from the main result
return function(results,source,widget) {
$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));
@@ -270,7 +274,7 @@ exports.compileFilter = function(filterString) {
})());
});
// Return a function that applies the operations to a source iterator of tiddler titles
return $tw.perf.measure("filter",function filterFunction(source,widget) {
return $tw.perf.measure("filter: " + filterString,function filterFunction(source,widget) {
if(!source) {
source = self.each;
} else if(typeof source === "object") { // Array or hashmap
+30
View File
@@ -0,0 +1,30 @@
/*\
title: $:/core/modules/filters/else.js
type: application/javascript
module-type: filteroperator
Filter operator for replacing an empty input list with a constant, passing a non-empty input list straight through
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.else = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(title);
});
if(results.length === 0) {
return [operator.operand];
} else {
return results;
}
};
})();
+9
View File
@@ -98,4 +98,13 @@ exports.escaperegexp = function(source,operator,options) {
return results;
};
exports.escapecss = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
// escape any character with a special meaning in CSS using CSS.escape()
results.push(CSS.escape(title));
});
return results;
};
})();
+10 -1
View File
@@ -16,7 +16,16 @@ Filter operator returning its operand parsed as a list
Export our filter function
*/
exports.enlist = function(source,operator,options) {
var list = $tw.utils.parseStringArray(operator.operand);
var allowDuplicates = false;
switch(operator.suffix) {
case "raw":
allowDuplicates = true;
break;
case "dedupe":
allowDuplicates = false;
break;
}
var list = $tw.utils.parseStringArray(operator.operand,allowDuplicates);
if(operator.prefix === "!") {
var results = [];
source(function(tiddler,title) {
+7 -1
View File
@@ -16,7 +16,7 @@ Filter operator for comparing fields for equality
Export our filter function
*/
exports.field = function(source,operator,options) {
var results = [],
var results = [],indexedResults,
fieldname = (operator.suffix || operator.operator || "title").toLowerCase();
if(operator.prefix === "!") {
if(operator.regexp) {
@@ -53,6 +53,12 @@ exports.field = function(source,operator,options) {
}
});
} else {
if(source.byField) {
indexedResults = source.byField(fieldname,operator.operand);
if(indexedResults) {
return indexedResults
}
}
source(function(tiddler,title) {
if(tiddler) {
var text = tiddler.getFieldString(fieldname);
+26
View File
@@ -0,0 +1,26 @@
/*\
title: $:/core/modules/filters/getvariable.js
type: application/javascript
module-type: filteroperator
Filter operator for replacing input values by the value of the variable with the same name, or blank if the variable is missing
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.getvariable = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.widget.getVariable(title) || "");
});
return results;
};
})();
+1 -1
View File
@@ -45,7 +45,7 @@ exports.has = function(source,operator,options) {
if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && !(tiddler.fields[operator.operand] === "" || tiddler.fields[operator.operand].length === 0)) {
results.push(title);
}
});
});
}
}
return results;
+36
View File
@@ -0,0 +1,36 @@
/*\
title: $:/core/modules/filters/is/blank.js
type: application/javascript
module-type: isfilteroperator
Filter function for [is[blank]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.blank = function(source,prefix,options) {
var results = [];
if(prefix === "!") {
source(function(tiddler,title) {
if(title) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(!title) {
results.push(title);
}
});
}
return results;
};
})();
+36
View File
@@ -0,0 +1,36 @@
/*\
title: $:/core/modules/filters/is/variable.js
type: application/javascript
module-type: isfilteroperator
Filter function for [is[variable]]
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.variable = function(source,prefix,options) {
var results = [];
if(prefix === "!") {
source(function(tiddler,title) {
if(!(title in options.widget.variables)) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title in options.widget.variables) {
results.push(title);
}
});
}
return results;
};
})();
+53
View File
@@ -0,0 +1,53 @@
/*\
title: $:/core/modules/filters/match.js
type: application/javascript
module-type: filteroperator
Filter operator for checking if a title matches a string
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.match = function(source,operator,options) {
var results = [],
suffixes = (operator.suffixes || [])[0] || [];
if(suffixes.indexOf("caseinsensitive") !== -1) {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title.toLowerCase() !== (operator.operand || "").toLowerCase()) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title.toLowerCase() === (operator.operand || "").toLowerCase()) {
results.push(title);
}
});
}
} else {
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(title !== operator.operand) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title === operator.operand) {
results.push(title);
}
});
}
}
return results;
};
})();
+146
View File
@@ -0,0 +1,146 @@
/*\
title: $:/core/modules/filters/math.js
type: application/javascript
module-type: filteroperator
Filter operators for math. Unary/binary operators work on each item in turn, and return a new item list.
Sum/product/maxall/minall operate on the entire list, returning a single item.
Note that strings are converted to numbers automatically. Trailing non-digits are ignored.
* "" converts to 0
* "12kk" converts to 12
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.negate = makeNumericBinaryOperator(
function(a) {return -a}
);
exports.abs = makeNumericBinaryOperator(
function(a) {return Math.abs(a)}
);
exports.ceil = makeNumericBinaryOperator(
function(a) {return Math.ceil(a)}
);
exports.floor = makeNumericBinaryOperator(
function(a) {return Math.floor(a)}
);
exports.round = makeNumericBinaryOperator(
function(a) {return Math.round(a)}
);
exports.trunc = makeNumericBinaryOperator(
function(a) {return Math.trunc(a)}
);
exports.untrunc = makeNumericBinaryOperator(
function(a) {return Math.ceil(Math.abs(a)) * Math.sign(a)}
);
exports.sign = makeNumericBinaryOperator(
function(a) {return Math.sign(a)}
);
exports.add = makeNumericBinaryOperator(
function(a,b) {return a + b;}
);
exports.subtract = makeNumericBinaryOperator(
function(a,b) {return a - b;}
);
exports.multiply = makeNumericBinaryOperator(
function(a,b) {return a * b;}
);
exports.divide = makeNumericBinaryOperator(
function(a,b) {return a / b;}
);
exports.remainder = makeNumericBinaryOperator(
function(a,b) {return a % b;}
);
exports.max = makeNumericBinaryOperator(
function(a,b) {return Math.max(a,b);}
);
exports.min = makeNumericBinaryOperator(
function(a,b) {return Math.min(a,b);}
);
exports.fixed = makeNumericBinaryOperator(
function(a,b) {return Number.prototype.toFixed.call(a,Math.min(Math.max(b,0),100));}
);
exports.precision = makeNumericBinaryOperator(
function(a,b) {return Number.prototype.toPrecision.call(a,Math.min(Math.max(b,1),100));}
);
exports.exponential = makeNumericBinaryOperator(
function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));}
);
exports.sum = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
0 // Initial value
);
exports.product = makeNumericReducingOperator(
function(accumulator,value) {return accumulator * value},
1 // Initial value
);
exports.maxall = makeNumericReducingOperator(
function(accumulator,value) {return Math.max(accumulator,value)},
-Infinity // Initial value
);
exports.minall = makeNumericReducingOperator(
function(accumulator,value) {return Math.min(accumulator,value)},
Infinity // Initial value
);
function makeNumericBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [],
numOperand = parseNumber(operator.operand);
source(function(tiddler,title) {
result.push(stringifyNumber(fnCalc(parseNumber(title),numOperand)));
});
return result;
};
}
function makeNumericReducingOperator(fnCalc,initialValue) {
initialValue = initialValue || 0;
return function(source,operator,options) {
var result = [];
source(function(tiddler,title) {
result.push(title);
});
return [stringifyNumber(result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,parseNumber(currentValue));
},initialValue))];
};
}
function parseNumber(str) {
return parseFloat(str) || 0;
}
function stringifyNumber(num) {
return num + "";
}
})();
+1 -1
View File
@@ -18,7 +18,7 @@ Export our filter function
exports.removesuffix = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
if(title.substr(-operator.operand.length) === operator.operand) {
if(title && title.substr(-operator.operand.length) === operator.operand) {
results.push(title.substr(0,title.length - operator.operand.length));
}
});
+1
View File
@@ -43,6 +43,7 @@ exports.search = function(source,operator,options) {
caseSensitive: hasFlag("casesensitive"),
literal: hasFlag("literal"),
whitespace: hasFlag("whitespace"),
anchored: hasFlag("anchored"),
regexp: hasFlag("regexp"),
words: hasFlag("words")
});
+93
View File
@@ -0,0 +1,93 @@
/*\
title: $:/core/modules/filters/strings.js
type: application/javascript
module-type: filteroperator
Filter operators for strings. Unary/binary operators work on each item in turn, and return a new item list.
Sum/product/maxall/minall operate on the entire list, returning a single item.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.length = makeStringBinaryOperator(
function(a) {return ["" + ("" + a).length];}
);
exports.uppercase = makeStringBinaryOperator(
function(a) {return [("" + a).toUpperCase()];}
);
exports.lowercase = makeStringBinaryOperator(
function(a) {return [("" + a).toLowerCase()];}
);
exports.sentencecase = makeStringBinaryOperator(
function(a) {return [$tw.utils.toSentenceCase(a)];}
);
exports.titlecase = makeStringBinaryOperator(
function(a) {return [$tw.utils.toTitleCase(a)];}
);
exports.trim = makeStringBinaryOperator(
function(a) {return [$tw.utils.trim(a)];}
);
exports.split = makeStringBinaryOperator(
function(a,b) {return ("" + a).split(b);}
);
exports.join = makeStringReducingOperator(
function(accumulator,value,operand) {
if(accumulator === null) {
return value;
} else {
return accumulator + operand + value;
}
},null
);
function makeStringBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [];
source(function(tiddler,title) {
Array.prototype.push.apply(result,fnCalc(title,operator.operand || ""));
});
return result;
};
}
function makeStringReducingOperator(fnCalc,initialValue) {
return function(source,operator,options) {
var result = [];
source(function(tiddler,title) {
result.push(title);
});
return [result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,currentValue,operator.operand || "");
},initialValue)];
};
}
exports.splitregexp = function(source,operator,options) {
var result = [],
suffix = operator.suffix || "",
flags = (suffix.indexOf("m") !== -1 ? "m" : "") + (suffix.indexOf("i") !== -1 ? "i" : ""),
regExp;
try {
regExp = new RegExp(operator.operand || "",flags);
} catch(ex) {
return ["RegExp error: " + ex];
}
source(function(tiddler,title) {
Array.prototype.push.apply(result,title.split(regExp));
});
return result;
};
})();
+16 -7
View File
@@ -16,7 +16,7 @@ Filter operator for checking for the presence of a tag
Export our filter function
*/
exports.tag = function(source,operator,options) {
var results = [];
var results = [],indexedResults;
if((operator.suffix || "").toLowerCase() === "strict" && !operator.operand) {
// New semantics:
// Always return copy of input if operator.operand is missing
@@ -25,9 +25,10 @@ exports.tag = function(source,operator,options) {
});
} else {
// Old semantics:
var tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
var tiddlers;
if(operator.prefix === "!") {
// Returns a copy of the input if operator.operand is missing
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
source(function(tiddler,title) {
if(tiddlers.indexOf(title) === -1) {
results.push(title);
@@ -35,12 +36,20 @@ exports.tag = function(source,operator,options) {
});
} else {
// Returns empty results if operator.operand is missing
source(function(tiddler,title) {
if(tiddlers.indexOf(title) !== -1) {
results.push(title);
if(source.byTag) {
indexedResults = source.byTag(operator.operand);
if(indexedResults) {
return indexedResults;
}
});
results = options.wiki.sortByList(results,operator.operand);
} else {
tiddlers = options.wiki.getTiddlersWithTag(operator.operand);
source(function(tiddler,title) {
if(tiddlers.indexOf(title) !== -1) {
results.push(title);
}
});
results = options.wiki.sortByList(results,operator.operand);
}
}
}
return results;
+26
View File
@@ -0,0 +1,26 @@
/*\
title: $:/core/modules/filters/then.js
type: application/javascript
module-type: filteroperator
Filter operator for replacing any titles with a constant
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.then = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(operator.operand);
});
return results;
};
})();
+26
View File
@@ -0,0 +1,26 @@
/*\
title: $:/core/modules/filters/variables.js
type: application/javascript
module-type: filteroperator
Filter operator for returning the names of the active variables
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.variables = function(source,operator,options) {
var names = [];
for(var variable in options.widget.variables) {
names.push(variable);
}
return names.sort();
};
})();
+2 -2
View File
@@ -95,7 +95,7 @@ Extended filter operators to manipulate the current list.
exports.allafter = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index === -1 || index > (results.length - 2)) ? [] :
return (index === -1) ? [] :
(operator.suffix) ? results.slice(index) :
results.slice(index + 1);
};
@@ -106,7 +106,7 @@ Extended filter operators to manipulate the current list.
exports.allbefore = function (source, operator) {
var results = prepare_results(source),
index = results.indexOf(operator.operand);
return (index < 0) ? [] :
return (index === -1) ? [] :
(operator.suffix) ? results.slice(0, index + 1) :
results.slice(0, index);
};
+143
View File
@@ -0,0 +1,143 @@
/*\
title: $:/core/modules/indexers/field-indexer.js
type: application/javascript
module-type: indexer
Indexes the tiddlers with each field value
\*/
(function(){
/*jslint node: true, browser: true */
/*global modules: false */
"use strict";
var DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH = 128;
function FieldIndexer(wiki) {
this.wiki = wiki;
}
FieldIndexer.prototype.init = function() {
this.index = null;
this.maxIndexedValueLength = DEFAULT_MAXIMUM_INDEXED_VALUE_LENGTH;
this.addIndexMethods();
}
// Provided for testing
FieldIndexer.prototype.setMaxIndexedValueLength = function(length) {
this.index = null;
this.maxIndexedValueLength = length;
};
FieldIndexer.prototype.addIndexMethods = function() {
var self = this;
this.wiki.each.byField = function(name,value) {
var titles = self.wiki.allTitles(),
lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return titles.indexOf(title) !== -1;
});
};
this.wiki.eachShadow.byField = function(name,value) {
var titles = self.wiki.allShadowTitles(),
lookup = self.lookup(name,value);
return lookup && lookup.filter(function(title) {
return titles.indexOf(title) !== -1;
});
};
this.wiki.eachTiddlerPlusShadows.byField = function(name,value) {
var lookup = self.lookup(name,value);
return lookup ? lookup.slice(0) : null;
};
this.wiki.eachShadowPlusTiddlers.byField = function(name,value) {
var lookup = self.lookup(name,value);
return lookup ? lookup.slice(0) : null;
};
};
/*
Tear down and then rebuild the index as if all tiddlers have changed
*/
FieldIndexer.prototype.rebuild = function() {
// Invalidate the index so that it will be rebuilt when it is next used
this.index = null;
};
/*
Build the index for a particular field
*/
FieldIndexer.prototype.buildIndexForField = function(name) {
var self = this;
// Hashmap by field name of hashmap by field value of array of tiddler titles
this.index = this.index || Object.create(null);
this.index[name] = Object.create(null);
var baseIndex = this.index[name];
// Update the index for each tiddler
this.wiki.eachTiddlerPlusShadows(function(tiddler,title) {
if(name in tiddler.fields) {
var value = tiddler.getFieldString(name);
// Skip any values above the maximum length
if(value.length < self.maxIndexedValueLength) {
baseIndex[value] = baseIndex[value] || [];
baseIndex[value].push(title);
}
}
});
};
/*
Update the index in the light of a tiddler value changing; note that the title must be identical. (Renames are handled as a separate delete and create)
updateDescriptor: {old: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>},new: {tiddler: <tiddler>, shadow: <boolean>, exists: <boolean>}}
*/
FieldIndexer.prototype.update = function(updateDescriptor) {
var self = this;
// Don't do anything if the index hasn't been built yet
if(this.index === null) {
return;
}
// Remove the old tiddler from the index
if(updateDescriptor.old.tiddler) {
$tw.utils.each(this.index,function(indexEntry,name) {
if(name in updateDescriptor.old.tiddler.fields) {
var value = updateDescriptor.old.tiddler.getFieldString(name),
tiddlerList = indexEntry[value];
if(tiddlerList) {
var index = tiddlerList.indexOf(updateDescriptor.old.tiddler.fields.title);
if(index !== -1) {
tiddlerList.splice(index,1);
}
}
}
});
}
// Add the new tiddler to the index
if(updateDescriptor["new"].tiddler) {
$tw.utils.each(this.index,function(indexEntry,name) {
if(name in updateDescriptor["new"].tiddler.fields) {
var value = updateDescriptor["new"].tiddler.getFieldString(name);
if(value.length < self.maxIndexedValueLength) {
indexEntry[value] = indexEntry[value] || [];
indexEntry[value].push(updateDescriptor["new"].tiddler.fields.title);
}
}
});
}
};
// Lookup the given field returning a list of tiddler titles
FieldIndexer.prototype.lookup = function(name,value) {
// Fail the lookup if the value is too long
if(value.length >= this.maxIndexedValueLength) {
return null;
}
// Update the index if it has yet to be built
if(this.index === null || !this.index[name]) {
this.buildIndexForField(name);
}
return this.index[name][value] || [];
};
exports.FieldIndexer = FieldIndexer;
})();
+98
View File
@@ -0,0 +1,98 @@
/*\
title: $:/core/modules/indexers/tag-indexer.js
type: application/javascript
module-type: indexer
Indexes the tiddlers with each tag
\*/
(function(){
/*jslint node: true, browser: true */
/*global modules: false */
"use strict";
function TagIndexer(wiki) {
this.wiki = wiki;
}
TagIndexer.prototype.init = function() {
this.subIndexers = [
new TagSubIndexer(this,"each"),
new TagSubIndexer(this,"eachShadow"),
new TagSubIndexer(this,"eachTiddlerPlusShadows"),
new TagSubIndexer(this,"eachShadowPlusTiddlers")
];
$tw.utils.each(this.subIndexers,function(subIndexer) {
subIndexer.addIndexMethod();
});
};
TagIndexer.prototype.rebuild = function() {
$tw.utils.each(this.subIndexers,function(subIndexer) {
subIndexer.rebuild();
});
};
TagIndexer.prototype.update = function(updateDescriptor) {
$tw.utils.each(this.subIndexers,function(subIndexer) {
subIndexer.update(updateDescriptor);
});
};
function TagSubIndexer(indexer,iteratorMethod) {
this.indexer = indexer;
this.iteratorMethod = iteratorMethod;
this.index = null; // Hashmap of tag title to {isSorted: bool, titles: [array]} or null if not yet initialised
}
TagSubIndexer.prototype.addIndexMethod = function() {
var self = this;
this.indexer.wiki[this.iteratorMethod].byTag = function(tag) {
return self.lookup(tag).slice(0);
};
};
TagSubIndexer.prototype.rebuild = function() {
var self = this;
// Hashmap by tag of array of {isSorted:, titles:[]}
this.index = Object.create(null);
// Add all the tags
this.indexer.wiki[this.iteratorMethod](function(tiddler,title) {
$tw.utils.each(tiddler.fields.tags,function(tag) {
if(!self.index[tag]) {
self.index[tag] = {isSorted: false, titles: [title]};
} else {
self.index[tag].titles.push(title);
}
});
});
};
TagSubIndexer.prototype.update = function(updateDescriptor) {
this.index = null;
};
TagSubIndexer.prototype.lookup = function(tag) {
// Update the index if it has yet to be built
if(this.index === null) {
this.rebuild();
}
var indexRecord = this.index[tag];
if(indexRecord) {
if(!indexRecord.isSorted) {
if(this.indexer.wiki.sortByList) {
indexRecord.titles = this.indexer.wiki.sortByList(indexRecord.titles,tag);
}
indexRecord.isSorted = true;
}
return indexRecord.titles;
} else {
return [];
}
};
exports.TagIndexer = TagIndexer;
})();
+2
View File
@@ -35,6 +35,8 @@ exports.getInfoTiddlerFields = function() {
// Screen size
infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()});
infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()});
// Language
infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""});
}
return infoTiddlerFields;
};
-41
View File
@@ -1,41 +0,0 @@
/*\
title: $:/core/modules/macros/dumpvariables.js
type: application/javascript
module-type: macro
Macro to dump all active variable values
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Information about this macro
*/
exports.name = "dumpvariables";
exports.params = [
];
/*
Run the macro
*/
exports.run = function() {
var output = ["|!Variable |!Value |"],
variables = [], variable;
for(variable in this.variables) {
variables.push(variable);
}
variables.sort();
for(var index=0; index<variables.length; index++) {
var variable = variables[index];
output.push("|" + variable + " |<input size=50 value=<<" + variable + ">>/> |")
}
return output.join("\n");
};
})();
+34
View File
@@ -0,0 +1,34 @@
/*\
title: $:/core/modules/macros/unusedtitle.js
type: application/javascript
module-type: macro
Macro to return a new title that is unused in the wiki. It can be given a name as a base.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Information about this macro
*/
exports.name = "unusedtitle";
exports.params = [
{name: "baseName"},
{name: "options"}
];
/*
Run the macro
*/
exports.run = function(baseName, options) {
if(!baseName) {
baseName = $tw.language.getString("DefaultNewTiddlerTitle");
}
return this.wiki.generateNewTitle(baseName, options);
};
})();
+14 -7
View File
@@ -21,6 +21,7 @@ function SaverHandler(options) {
var self = this;
this.wiki = options.wiki;
this.dirtyTracking = options.dirtyTracking;
this.preloadDirty = options.preloadDirty || [];
this.pendingAutoSave = false;
// Make a logger
this.logger = new $tw.utils.Logger("saver-handler");
@@ -33,7 +34,13 @@ function SaverHandler(options) {
// Compile the dirty tiddler filter
this.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));
// Count of changes that have not yet been saved
this.numChanges = 0;
var filteredChanges = self.filterFn.call(self.wiki,function(iterator) {
$tw.utils.each(self.preloadDirty,function(title) {
var tiddler = self.wiki.getTiddler(title);
iterator(tiddler,title);
});
});
this.numChanges = filteredChanges.length;
// Listen out for changes to tiddlers
this.wiki.addEventListener("change",function(changes) {
// Filter the changes so that we only count changes to tiddlers that we care about
@@ -144,8 +151,12 @@ Save the wiki contents. Options are:
SaverHandler.prototype.saveWiki = function(options) {
options = options || {};
var self = this,
method = options.method || "save",
variables = options.variables || {},
method = options.method || "save";
// Ignore autosave if disabled
if(method === "autosave" && this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes") {
return false;
}
var variables = options.variables || {},
template = options.template || "$:/core/save/all",
downloadType = options.downloadType || "text/plain",
text = this.wiki.renderTiddler(downloadType,template,options),
@@ -164,10 +175,6 @@ SaverHandler.prototype.saveWiki = function(options) {
}
}
};
// Ignore autosave if disabled
if(method === "autosave" && this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes") {
return false;
}
// Call the highest priority saver that supports this method
for(var t=this.savers.length-1; t>=0; t--) {
var saver = this.savers[t];
+118
View File
@@ -0,0 +1,118 @@
/*\
title: $:/core/modules/savers/github.js
type: application/javascript
module-type: saver
Saves wiki by pushing a commit to the GitHub v3 REST API
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Select the appropriate saver module and set it up
*/
var GitHubSaver = function(wiki) {
this.wiki = wiki;
};
GitHubSaver.prototype.save = function(text,method,callback) {
var self = this,
username = this.wiki.getTiddlerText("$:/GitHub/Username"),
password = $tw.utils.getPassword("github"),
repo = this.wiki.getTiddlerText("$:/GitHub/Repo"),
path = this.wiki.getTiddlerText("$:/GitHub/Path"),
filename = this.wiki.getTiddlerText("$:/GitHub/Filename"),
branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "master",
endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com",
headers = {
"Accept": "application/vnd.github.v3+json",
"Content-Type": "application/json;charset=UTF-8",
"Authorization": "Basic " + window.btoa(username + ":" + password)
};
// Bail if we don't have everything we need
if(!username || !password || !repo || !path || !filename) {
return false;
}
// Make sure the path start and ends with a slash
if(path.substring(0,1) !== "/") {
path = "/" + path;
}
if(path.substring(path.length - 1) !== "/") {
path = path + "/";
}
// Compose the base URI
var uri = endpoint + "/repos/" + repo + "/contents" + path;
// Perform a get request to get the details (inc shas) of files in the same path as our file
$tw.utils.httpRequest({
url: uri,
type: "GET",
headers: headers,
data: {
ref: branch
},
callback: function(err,getResponseDataJson,xhr) {
var getResponseData,sha = "";
if(err && xhr.status !== 404) {
return callback(err);
}
if(xhr.status !== 404) {
getResponseData = JSON.parse(getResponseDataJson);
$tw.utils.each(getResponseData,function(details) {
if(details.name === filename) {
sha = details.sha;
}
});
}
var data = {
message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
content: $tw.utils.base64Encode(text),
branch: branch,
sha: sha
};
// Perform a PUT request to save the file
$tw.utils.httpRequest({
url: uri + filename,
type: "PUT",
headers: headers,
data: JSON.stringify(data),
callback: function(err,putResponseDataJson,xhr) {
if(err) {
return callback(err);
}
var putResponseData = JSON.parse(putResponseDataJson);
callback(null);
}
});
}
});
return true;
};
/*
Information about this saver
*/
GitHubSaver.prototype.info = {
name: "github",
priority: 2000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return true;
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new GitHubSaver(wiki);
};
})();
+120
View File
@@ -0,0 +1,120 @@
/*\
title: $:/core/modules/savers/gitlab.js
type: application/javascript
module-type: saver
Saves wiki by pushing a commit to the GitLab REST API
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: true */
"use strict";
/*
Select the appropriate saver module and set it up
*/
var GitLabSaver = function(wiki) {
this.wiki = wiki;
};
GitLabSaver.prototype.save = function(text,method,callback) {
/* See https://docs.gitlab.com/ee/api/repository_files.html */
var self = this,
username = this.wiki.getTiddlerText("$:/GitLab/Username"),
password = $tw.utils.getPassword("gitlab"),
repo = this.wiki.getTiddlerText("$:/GitLab/Repo"),
path = this.wiki.getTiddlerText("$:/GitLab/Path"),
filename = this.wiki.getTiddlerText("$:/GitLab/Filename"),
branch = this.wiki.getTiddlerText("$:/GitLab/Branch") || "master",
endpoint = this.wiki.getTiddlerText("$:/GitLab/ServerURL") || "https://gitlab.com/api/v4",
headers = {
"Content-Type": "application/json;charset=UTF-8",
"Private-Token": password
};
// Bail if we don't have everything we need
if(!username || !password || !repo || !path || !filename) {
return false;
}
// Make sure the path start and ends with a slash
if(path.substring(0,1) !== "/") {
path = "/" + path;
}
if(path.substring(path.length - 1) !== "/") {
path = path + "/";
}
// Compose the base URI
var uri = endpoint + "/projects/" + encodeURIComponent(repo) + "/repository/";
// Perform a get request to get the details (inc shas) of files in the same path as our file
$tw.utils.httpRequest({
url: uri + "tree/" + encodeURIComponent(path.replace(/^\/+|\/$/g, '')),
type: "GET",
headers: headers,
data: {
ref: branch
},
callback: function(err,getResponseDataJson,xhr) {
var getResponseData,sha = "";
if(err && xhr.status !== 404) {
return callback(err);
}
var requestType = "POST";
if(xhr.status !== 404) {
getResponseData = JSON.parse(getResponseDataJson);
$tw.utils.each(getResponseData,function(details) {
if(details.name === filename) {
requestType = "PUT";
sha = details.sha;
}
});
}
var data = {
commit_message: $tw.language.getRawString("ControlPanel/Saving/GitService/CommitMessage"),
content: $tw.utils.base64Encode(text),
branch: branch,
sha: sha
};
// Perform a request to save the file
$tw.utils.httpRequest({
url: uri + "files/" + encodeURIComponent(path.replace(/^\/+/, '') + filename),
type: requestType,
headers: headers,
data: JSON.stringify(data),
callback: function(err,putResponseDataJson,xhr) {
if(err) {
return callback(err);
}
var putResponseData = JSON.parse(putResponseDataJson);
callback(null);
}
});
}
});
return true;
};
/*
Information about this saver
*/
GitLabSaver.prototype.info = {
name: "gitlab",
priority: 2000,
capabilities: ["save", "autosave"]
};
/*
Static method that returns true if this saver is capable of working
*/
exports.canSave = function(wiki) {
return true;
};
/*
Create an instance of this saver
*/
exports.create = function(wiki) {
return new GitLabSaver(wiki);
};
})();
+1 -1
View File
@@ -41,7 +41,7 @@ BasicAuthenticator.prototype.init = function() {
this.credentialsData = credentialsData;
}
} else {
return "Error: Unable to load user credentials from '" + credentialsFilepath + "'";
return "Error: Unable to load user credentials from '" + resolveCredentialsFilepath + "'";
}
}
// Add the hardcoded username and password if specified
+28 -2
View File
@@ -12,14 +12,40 @@ GET /
/*global $tw: false */
"use strict";
var zlib = require('zlib');
exports.method = "GET";
exports.path = /^\/$/;
exports.handler = function(request,response,state) {
response.writeHead(200, {"Content-Type": state.server.get("root-serve-type")});
var acceptEncoding = request.headers['accept-encoding'];
if (!acceptEncoding) { acceptEncoding = ''; }
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler"));
response.end(text,"utf8");
var responseHeaders = {
"Content-Type": state.server.get("root-serve-type")
};
/*
If the gzip=yes flag for `listen` is set, check if the user agent permits
compression. If so, compress our response. Note that we use the synchronous
functions from zlib to stay in the imperative style. The current `Server`
doesn't depend on this, and we may just as well use the async versions.
*/
if(state.server.enableGzip) {
if (/\bdeflate\b/.test(acceptEncoding)) {
responseHeaders['Content-Encoding'] = 'deflate';
text = zlib.deflateSync(text);
} else if (/\bgzip\b/.test(acceptEncoding)) {
responseHeaders['Content-Encoding'] = 'gzip';
text = zlib.gzipSync(text);
}
}
response.writeHead(200, responseHeaders);
response.end(text);
};
}());
+9 -4
View File
@@ -43,6 +43,8 @@ function Server(options) {
$tw.utils.extend({},this.defaultVariables,options.variables);
// Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression
this.enableGzip = this.get("gzip") === "yes";
// Initialise authorization
var authorizedUserName = (this.get("username") && this.get("password")) ? this.get("username") : "(anon)";
this.authorizationPrincipals = {
@@ -84,7 +86,8 @@ Server.prototype.defaultVariables = {
"tiddler-render-template": "$:/core/templates/server/static.tiddler.html",
"system-tiddler-render-type": "text/plain",
"system-tiddler-render-template": "$:/core/templates/wikified-tiddler",
"debug-level": "none"
"debug-level": "none",
"gzip": "no"
};
Server.prototype.get = function(name) {
@@ -229,17 +232,19 @@ Server.prototype.requestHandler = function(request,response) {
/*
Listen for requests
port: optional port number (falls back to value of "port" variable)
host: optional host address (falls back to value of "hist" variable)
host: optional host address (falls back to value of "host" variable)
prefix: optional prefix (falls back to value of "path-prefix" variable)
*/
Server.prototype.listen = function(port,host) {
Server.prototype.listen = function(port,host,prefix) {
// Handle defaults for port and host
port = port || this.get("port");
host = host || this.get("host");
prefix = prefix || this.get("path-prefix") || "";
// Check for the port being a string and look it up as an environment variable
if(parseInt(port,10).toString() !== port) {
port = process.env[port] || 8080;
}
$tw.utils.log("Serving on " + this.protocol + "://" + host + ":" + port,"brown/orange");
$tw.utils.log("Serving on " + this.protocol + "://" + host + ":" + port + prefix,"brown/orange");
$tw.utils.log("(press ctrl-C to exit)","red");
// Warn if required plugins are missing
if(!$tw.wiki.getTiddler("$:/plugins/tiddlywiki/tiddlyweb") || !$tw.wiki.getTiddler("$:/plugins/tiddlywiki/filesystem")) {
+3 -3
View File
@@ -144,9 +144,9 @@ exports.startup = function() {
});
// Listen for window messages from other windows
window.addEventListener("message",function listener(event){
console.log("browser-messaging: ",document.location.toString())
console.log("browser-messaging: Received message from",event.origin);
console.log("browser-messaging: Message content",event.data);
// console.log("browser-messaging: ",document.location.toString())
// console.log("browser-messaging: Received message from",event.origin);
// console.log("browser-messaging: Message content",event.data);
switch(event.data.verb) {
case "GET-RESPONSE":
if(event.data.status.charAt(0) === "2") {
+114
View File
@@ -0,0 +1,114 @@
/*\
title: $:/core/modules/startup/CSSescape.js
type: application/javascript
module-type: startup
Polyfill for CSS.escape()
\*/
(function(root,factory){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "css-escape";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
/*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
// https://github.com/umdjs/umd/blob/master/returnExports.js
exports.startup = factory(root);
}(typeof global != 'undefined' ? global : this, function(root) {
if (root.CSS && root.CSS.escape) {
return;
}
// https://drafts.csswg.org/cssom/#serialize-an-identifier
var cssEscape = function(value) {
if (arguments.length == 0) {
throw new TypeError('`CSS.escape` requires an argument.');
}
var string = String(value);
var length = string.length;
var index = -1;
var codeUnit;
var result = '';
var firstCodeUnit = string.charCodeAt(0);
while (++index < length) {
codeUnit = string.charCodeAt(index);
// Note: theres no need to special-case astral symbols, surrogate
// pairs, or lone surrogates.
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
// (U+FFFD).
if (codeUnit == 0x0000) {
result += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
// If the character is the first character and is in the range [0-9]
// (U+0030 to U+0039), […]
(index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
// If the character is the second character and is in the range [0-9]
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
(
index == 1 &&
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
firstCodeUnit == 0x002D
)
) {
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
result += '\\' + codeUnit.toString(16) + ' ';
continue;
}
if (
// If the character is the first character and is a `-` (U+002D), and
// there is no second character, […]
index == 0 &&
length == 1 &&
codeUnit == 0x002D
) {
result += '\\' + string.charAt(index);
continue;
}
// If the character is not handled by one of the above rules and is
// greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
// is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
// U+005A), or [a-z] (U+0061 to U+007A), […]
if (
codeUnit >= 0x0080 ||
codeUnit == 0x002D ||
codeUnit == 0x005F ||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
codeUnit >= 0x0061 && codeUnit <= 0x007A
) {
// the character itself
result += string.charAt(index);
continue;
}
// Otherwise, the escaped character.
// https://drafts.csswg.org/cssom/#escape-a-character
result += '\\' + string.charAt(index);
}
return result;
};
if (!root.CSS) {
root.CSS = {};
}
root.CSS.escape = cssEscape;
}));
+1
View File
@@ -27,6 +27,7 @@ exports.startup = function() {
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
$tw.wiki.addIndexersToWiki();
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
$tw.wiki.initParsers();
+2 -1
View File
@@ -71,9 +71,10 @@ exports.startup = function() {
timerId;
function refresh() {
// Process the refresh
$tw.hooks.invokeHook("th-page-refreshing");
$tw.pageWidgetNode.refresh(deferredChanges);
deferredChanges = Object.create(null);
$tw.hooks.invokeHook("th-page-refreshed");
$tw.hooks.invokeHook("th-page-refreshed");
}
// Add the change event handler
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
+19 -5
View File
@@ -34,6 +34,19 @@ exports.startup = function() {
$tw.rootWidget.addEventListener("tm-copy-to-clipboard",function(event) {
$tw.utils.copyToClipboard(event.param);
});
// Install the tm-focus-selector message
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
var selector = event.param || "",
element;
try {
element = document.querySelector(selector);
} catch(e) {
console.log("Error in selector: ",selector)
}
if(element && element.focus) {
element.focus(event.paramObject);
}
});
// Install the scroller
$tw.pageScroller = new $tw.utils.PageScroller();
$tw.rootWidget.addEventListener("tm-scroll",function(event) {
@@ -42,15 +55,16 @@ exports.startup = function() {
var fullscreen = $tw.utils.getFullScreenApis();
if(fullscreen) {
$tw.rootWidget.addEventListener("tm-full-screen",function(event) {
var fullScreenDocument = event.event ? event.event.target.ownerDocument : document;
if(event.param === "enter") {
event.event.target.ownerDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
fullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
} else if(event.param === "exit") {
event.event.target.ownerDocument[fullscreen._exitFullscreen]();
fullScreenDocument[fullscreen._exitFullscreen]();
} else {
if(event.event.target.ownerDocument[fullscreen._fullscreenElement]) {
event.event.target.ownerDocument[fullscreen._exitFullscreen]();
if(fullScreenDocument[fullscreen._fullscreenElement]) {
fullScreenDocument[fullscreen._exitFullscreen]();
} else {
event.event.target.ownerDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
fullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
}
}
});
+27 -23
View File
@@ -55,6 +55,27 @@ exports.startup = function() {
$tw.version = $tw.utils.extractVersionInfo();
// Set up the performance framework
$tw.perf = new $tw.Performance($tw.wiki.getTiddlerText(PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE,"no") === "yes");
// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers
$tw.rootWidget = new widget.widget({
type: "widget",
children: []
},{
wiki: $tw.wiki,
document: $tw.browser ? document : $tw.fakeDocument
});
// Execute any startup actions
var executeStartupTiddlers = function(tag) {
$tw.utils.each($tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[" + tag + "]!has[draft.of]]"),function(title) {
$tw.rootWidget.invokeActionString($tw.wiki.getTiddlerText(title),$tw.rootWidget);
});
};
executeStartupTiddlers("$:/tags/StartupAction");
if($tw.browser) {
executeStartupTiddlers("$:/tags/StartupAction/Browser");
}
if($tw.node) {
executeStartupTiddlers("$:/tags/StartupAction/Node");
}
// Kick off the language manager and switcher
$tw.language = new $tw.Language();
$tw.languageSwitcher = new $tw.PluginSwitcher({
@@ -62,7 +83,7 @@ exports.startup = function() {
pluginType: "language",
controllerTitle: "$:/language",
defaultPlugins: [
"$:/languages/en-US"
"$:/languages/en-GB"
],
onSwitch: function(plugins) {
if($tw.browser) {
@@ -95,27 +116,6 @@ exports.startup = function() {
handlerMethod: "handleKeydownEvent"
}]);
}
// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers
$tw.rootWidget = new widget.widget({
type: "widget",
children: []
},{
wiki: $tw.wiki,
document: $tw.browser ? document : $tw.fakeDocument
});
// Execute any startup actions
var executeStartupTiddlers = function(tag) {
$tw.utils.each($tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[" + tag + "]!has[draft.of]]"),function(title) {
$tw.rootWidget.invokeActionString($tw.wiki.getTiddlerText(title),$tw.rootWidget);
});
};
executeStartupTiddlers("$:/tags/StartupAction");
if($tw.browser) {
executeStartupTiddlers("$:/tags/StartupAction/Browser");
}
if($tw.node) {
executeStartupTiddlers("$:/tags/StartupAction/Node");
}
// Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup
$tw.wiki.clearTiddlerEventQueue();
// Find a working syncadaptor
@@ -130,7 +130,11 @@ exports.startup = function() {
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});
}
// Setup the saver handler
$tw.saverHandler = new $tw.SaverHandler({wiki: $tw.wiki, dirtyTracking: !$tw.syncadaptor});
$tw.saverHandler = new $tw.SaverHandler({
wiki: $tw.wiki,
dirtyTracking: !$tw.syncadaptor,
preloadDirty: $tw.boot.preloadDirty || []
});
// Host-specific startup
if($tw.browser) {
// Install the popup manager
+16 -10
View File
@@ -36,7 +36,9 @@ var HELP_OPEN_EXTERNAL_WINDOW = "http://tiddlywiki.com/#WidgetMessage%3A%20tm-op
exports.startup = function() {
// Open startup tiddlers
openStartupTiddlers();
openStartupTiddlers({
disableHistory: $tw.boot.disableStartupNavigation
});
if($tw.browser) {
// Set up location hash update
$tw.wiki.addEventListener("change",function(changes) {
@@ -106,6 +108,7 @@ exports.startup = function() {
/*
Process the location hash to open the specified tiddlers. Options:
disableHistory: if true $:/History is NOT updated
defaultToCurrentStory: If true, the current story is retained as the default, instead of opening the default tiddlers
*/
function openStartupTiddlers(options) {
@@ -146,15 +149,18 @@ function openStartupTiddlers(options) {
}
// Save the story list
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
// If a target tiddler was specified add it to the history stack
if(target && target !== "") {
// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
target = target.substr(2,target.length - 4);
}
$tw.wiki.addToHistory(target);
} else if(storyList.length > 0) {
$tw.wiki.addToHistory(storyList[0]);
// Update history
if(!options.disableHistory) {
// If a target tiddler was specified add it to the history stack
if(target && target !== "") {
// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
target = target.substr(2,target.length - 4);
}
$tw.wiki.addToHistory(target);
} else if(storyList.length > 0) {
$tw.wiki.addToHistory(storyList[0]);
}
}
}
+2 -1
View File
@@ -28,6 +28,7 @@ exports.startup = function() {
var refreshHandler,
title = event.param || event.tiddlerTitle,
paramObject = event.paramObject || {},
windowTitle = paramObject.windowTitle || title,
template = paramObject.template || "$:/core/templates/single.tiddler.window",
width = paramObject.width || "700",
height = paramObject.height || "600",
@@ -51,7 +52,7 @@ exports.startup = function() {
// Initialise the document
srcDocument.write("<html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
srcDocument.close();
srcDocument.title = title;
srcDocument.title = windowTitle;
srcWindow.addEventListener("beforeunload",function(event) {
delete windows[title];
$tw.wiki.removeEventListener("change",refreshHandler);
+74 -63
View File
@@ -19,6 +19,7 @@ var ClassicStoryView = function(listWidget) {
};
ClassicStoryView.prototype.navigateTo = function(historyInfo) {
var duration = $tw.utils.getAnimationDuration()
var listElementIndex = this.listWidget.findListItem(0,historyInfo.title);
if(listElementIndex === undefined) {
return;
@@ -29,80 +30,90 @@ ClassicStoryView.prototype.navigateTo = function(historyInfo) {
if(!(targetElement instanceof Element)) {
return;
}
// Scroll the node into view
this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement});
if(duration) {
// Scroll the node into view
this.listWidget.dispatchEvent({type: "tm-scroll", target: targetElement});
} else {
targetElement.scrollIntoView();
}
};
ClassicStoryView.prototype.insert = function(widget) {
var targetElement = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!(targetElement instanceof Element)) {
return;
}
// Get the current height of the tiddler
var computedStyle = window.getComputedStyle(targetElement),
currMarginBottom = parseInt(computedStyle.marginBottom,10),
currMarginTop = parseInt(computedStyle.marginTop,10),
currHeight = targetElement.offsetHeight + currMarginTop;
// Reset the margin once the transition is over
setTimeout(function() {
var duration = $tw.utils.getAnimationDuration();
if(duration) {
var targetElement = widget.findFirstDomNode();
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!(targetElement instanceof Element)) {
return;
}
// Get the current height of the tiddler
var computedStyle = window.getComputedStyle(targetElement),
currMarginBottom = parseInt(computedStyle.marginBottom,10),
currMarginTop = parseInt(computedStyle.marginTop,10),
currHeight = targetElement.offsetHeight + currMarginTop;
// Reset the margin once the transition is over
setTimeout(function() {
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{marginBottom: ""}
]);
},duration);
// Set up the initial position of the element
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{marginBottom: ""}
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
},duration);
// Set up the initial position of the element
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
$tw.utils.forceLayout(targetElement);
// Transition to the final position
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + duration + "ms " + easing + ", " +
"margin-bottom " + duration + "ms " + easing},
{marginBottom: currMarginBottom + "px"},
{opacity: "1.0"}
$tw.utils.forceLayout(targetElement);
// Transition to the final position
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + duration + "ms " + easing + ", " +
"margin-bottom " + duration + "ms " + easing},
{marginBottom: currMarginBottom + "px"},
{opacity: "1.0"}
]);
}
};
ClassicStoryView.prototype.remove = function(widget) {
var targetElement = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration(),
removeElement = function() {
widget.removeChildDomNodes();
};
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!(targetElement instanceof Element)) {
removeElement();
return;
var duration = $tw.utils.getAnimationDuration();
if(duration) {
var targetElement = widget.findFirstDomNode(),
removeElement = function() {
widget.removeChildDomNodes();
};
// Abandon if the list entry isn't a DOM element (it might be a text node)
if(!(targetElement instanceof Element)) {
removeElement();
return;
}
// Get the current height of the tiddler
var currWidth = targetElement.offsetWidth,
computedStyle = window.getComputedStyle(targetElement),
currMarginBottom = parseInt(computedStyle.marginBottom,10),
currMarginTop = parseInt(computedStyle.marginTop,10),
currHeight = targetElement.offsetHeight + currMarginTop;
// Remove the dom nodes of the widget at the end of the transition
setTimeout(removeElement,duration);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transform: "translateX(0px)"},
{marginBottom: currMarginBottom + "px"},
{opacity: "1.0"}
]);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
"opacity " + duration + "ms " + easing + ", " +
"margin-bottom " + duration + "ms " + easing},
{transform: "translateX(-" + currWidth + "px)"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
} else {
widget.removeChildDomNodes();
}
// Get the current height of the tiddler
var currWidth = targetElement.offsetWidth,
computedStyle = window.getComputedStyle(targetElement),
currMarginBottom = parseInt(computedStyle.marginBottom,10),
currMarginTop = parseInt(computedStyle.marginTop,10),
currHeight = targetElement.offsetHeight + currMarginTop;
// Remove the dom nodes of the widget at the end of the transition
setTimeout(removeElement,duration);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transform: "translateX(0px)"},
{marginBottom: currMarginBottom + "px"},
{opacity: "1.0"}
]);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + duration + "ms " + easing + ", " +
"opacity " + duration + "ms " + easing + ", " +
"margin-bottom " + duration + "ms " + easing},
{transform: "translateX(-" + currWidth + "px)"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
};
exports.classic = ClassicStoryView;
+8 -1
View File
@@ -44,7 +44,14 @@ PopStoryView.prototype.insert = function(widget) {
{transition: "none"},
{transform: "none"}
]);
$tw.utils.setStyle(widget.document.body,[
{"overflow-x": ""}
]);
},duration);
// Prevent the page from overscrolling due to the zoom factor
$tw.utils.setStyle(widget.document.body,[
{"overflow-x": "hidden"}
]);
// Set up the initial position of the element
$tw.utils.setStyle(targetElement,[
{transition: "none"},
@@ -65,7 +72,7 @@ PopStoryView.prototype.remove = function(widget) {
var targetElement = widget.findFirstDomNode(),
duration = $tw.utils.getAnimationDuration(),
removeElement = function() {
if(targetElement.parentNode) {
if(targetElement && targetElement.parentNode) {
widget.removeChildDomNodes();
}
};
+8 -59
View File
@@ -75,67 +75,16 @@ Get all the fields as a name:value block. Options:
*/
exports.getFieldStringBlock = function(options) {
options = options || {};
var exclude = options.exclude || [];
var fields = [];
for(var field in this.fields) {
if($tw.utils.hop(this.fields,field)) {
if(exclude.indexOf(field) === -1) {
fields.push(field + ": " + this.getFieldString(field));
}
var exclude = options.exclude || [],
fields = Object.keys(this.fields).sort(),
result = [];
for(var t=0; t<fields.length; t++) {
var field = fields[t];
if(exclude.indexOf(field) === -1) {
result.push(field + ": " + this.getFieldString(field));
}
}
return fields.join("\n");
};
/*
Compare two tiddlers for equality
tiddler: the tiddler to compare
excludeFields: array of field names to exclude from the comparison
*/
exports.isEqual = function(tiddler,excludeFields) {
if(!(tiddler instanceof $tw.Tiddler)) {
return false;
}
excludeFields = excludeFields || [];
var self = this,
differences = []; // Fields that have differences
// Add to the differences array
function addDifference(fieldName) {
// Check for this field being excluded
if(excludeFields.indexOf(fieldName) === -1) {
// Save the field as a difference
$tw.utils.pushTop(differences,fieldName);
}
}
// Returns true if the two values of this field are equal
function isFieldValueEqual(fieldName) {
var valueA = self.fields[fieldName],
valueB = tiddler.fields[fieldName];
// Check for identical string values
if(typeof(valueA) === "string" && typeof(valueB) === "string" && valueA === valueB) {
return true;
}
// Check for identical array values
if($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {
return true;
}
// Otherwise the fields must be different
return false;
}
// Compare our fields
for(var fieldName in this.fields) {
if(!isFieldValueEqual(fieldName)) {
addDifference(fieldName);
}
}
// There's a difference for every field in the other tiddler that we don't have
for(fieldName in tiddler.fields) {
if(!(fieldName in this.fields)) {
addDifference(fieldName);
}
}
// Return whether there were any differences
return differences.length === 0;
return result.join("\n");
};
exports.getFieldDay = function(field) {
+15 -2
View File
@@ -13,11 +13,13 @@ Upgrader module that suppresses certain system tiddlers that shouldn't be import
"use strict";
var DONT_IMPORT_LIST = ["$:/StoryList","$:/HistoryList"],
DONT_IMPORT_PREFIX_LIST = ["$:/temp/","$:/state/"];
DONT_IMPORT_PREFIX_LIST = ["$:/temp/","$:/state/","$:/Import"],
WARN_IMPORT_PREFIX_LIST = ["$:/core/modules/"];
exports.upgrade = function(wiki,titles,tiddlers) {
var self = this,
messages = {};
messages = {},
showAlert = false;
// Check for tiddlers on our list
$tw.utils.each(titles,function(title) {
if(DONT_IMPORT_LIST.indexOf(title) !== -1) {
@@ -31,6 +33,17 @@ exports.upgrade = function(wiki,titles,tiddlers) {
messages[title] = $tw.language.getString("Import/Upgrader/State/Suppressed");
}
}
for(var t=0; t<WARN_IMPORT_PREFIX_LIST.length; t++) {
var prefix = WARN_IMPORT_PREFIX_LIST[t];
if(title.substr(0,prefix.length) === prefix) {
showAlert = true;
messages[title] = $tw.language.getString("Import/Upgrader/System/Warning");
}
}
}
if(showAlert) {
var logger = new $tw.utils.Logger("import");
logger.alert($tw.language.getString("Import/Upgrader/System/Alert"));
}
});
return messages;
@@ -0,0 +1,124 @@
// From https://gist.github.com/Nijikokun/5192472
//
// UTF8 Module
//
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
//
// copyright: MIT
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
(function (name, definition, context, dependencies) {
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
else { context[name] = definition.apply(context); }
})('utf8', function () {
return {
encode: function (string) {
if (typeof string !== 'string') return string;
else string = string.replace(/\r\n/g, "\n");
var output = "", i = 0, charCode;
for (i; i < string.length; i++) {
charCode = string.charCodeAt(i);
if (charCode < 128)
output += String.fromCharCode(charCode);
else if ((charCode > 127) && (charCode < 2048))
output += String.fromCharCode((charCode >> 6) | 192),
output += String.fromCharCode((charCode & 63) | 128);
else
output += String.fromCharCode((charCode >> 12) | 224),
output += String.fromCharCode(((charCode >> 6) & 63) | 128),
output += String.fromCharCode((charCode & 63) | 128);
}
return output;
},
decode: function (string) {
if (typeof string !== 'string') return string;
var output = "", i = 0, charCode = 0;
while (i < string.length) {
charCode = string.charCodeAt(i);
if (charCode < 128)
output += String.fromCharCode(charCode),
i++;
else if ((charCode > 191) && (charCode < 224))
output += String.fromCharCode(((charCode & 31) << 6) | (string.charCodeAt(i + 1) & 63)),
i += 2;
else
output += String.fromCharCode(((charCode & 15) << 12) | ((string.charCodeAt(i + 1) & 63) << 6) | (string.charCodeAt(i + 2) & 63)),
i += 3;
}
return output;
}
};
}, this);
// Base64 Module
//
// Cleaner, modularized and properly scoped base64 encoding and decoding module for strings.
//
// copyright: MIT
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
(function (name, definition, context, dependencies) {
if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['amd']) { define(name, (dependencies || []), definition); }
else { context[name] = definition.apply(context); }
})('base64', function (utf8) {
var $this = this;
var $utf8 = utf8 || this.utf8;
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function (input) {
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
if (typeof input !== 'string') return input;
else input = $utf8.encode(input);
var output = "", a, b, c, d, e, f, g, i = 0;
while (i < input.length) {
a = input.charCodeAt(i++);
b = input.charCodeAt(i++);
c = input.charCodeAt(i++);
d = a >> 2;
e = ((a & 3) << 4) | (b >> 4);
f = ((b & 15) << 2) | (c >> 6);
g = c & 63;
if (isNaN(b)) f = g = 64;
else if (isNaN(c)) g = 64;
output += map.charAt(d) + map.charAt(e) + map.charAt(f) + map.charAt(g);
}
return output;
},
decode: function (input) {
if (typeof $utf8 === 'undefined') throw { error: "MissingMethod", message: "UTF8 Module is missing." };
if (typeof input !== 'string') return input;
else input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
var output = "", a, b, c, d, e, f, g, i = 0;
while (i < input.length) {
d = map.indexOf(input.charAt(i++));
e = map.indexOf(input.charAt(i++));
f = map.indexOf(input.charAt(i++));
g = map.indexOf(input.charAt(i++));
a = (d << 2) | (e >> 4);
b = ((e & 15) << 4) | (f >> 2);
c = ((f & 3) << 6) | g;
output += String.fromCharCode(a);
if (f != 64) output += String.fromCharCode(b);
if (g != 64) output += String.fromCharCode(c);
}
return $utf8.decode(output);
}
}
}, this, [ "utf8" ]);
@@ -0,0 +1,9 @@
// From https://gist.github.com/Nijikokun/5192472
//
// UTF8 Module
//
// Cleaner and modularized utf-8 encoding and decoding library for javascript.
//
// copyright: MIT
// author: Nijiko Yonskai, @nijikokun, nijikokun@gmail.com
!function(r,e,o,t){void 0!==o.module&&o.module.exports?o.module.exports=e.apply(o):void 0!==o.define&&"function"===o.define&&o.define.amd?define("utf8",[],e):o.utf8=e.apply(o)}(0,function(){return{encode:function(r){if("string"!=typeof r)return r;r=r.replace(/\r\n/g,"\n");for(var e,o="",t=0;t<r.length;t++)(e=r.charCodeAt(t))<128?o+=String.fromCharCode(e):e>127&&e<2048?(o+=String.fromCharCode(e>>6|192),o+=String.fromCharCode(63&e|128)):(o+=String.fromCharCode(e>>12|224),o+=String.fromCharCode(e>>6&63|128),o+=String.fromCharCode(63&e|128));return o},decode:function(r){if("string"!=typeof r)return r;for(var e="",o=0,t=0;o<r.length;)(t=r.charCodeAt(o))<128?(e+=String.fromCharCode(t),o++):t>191&&t<224?(e+=String.fromCharCode((31&t)<<6|63&r.charCodeAt(o+1)),o+=2):(e+=String.fromCharCode((15&t)<<12|(63&r.charCodeAt(o+1))<<6|63&r.charCodeAt(o+2)),o+=3);return e}}},this),function(r,e,o,t){if(void 0!==o.module&&o.module.exports){if(t&&o.require)for(var n=0;n<t.length;n++)o[t[n]]=o.require(t[n]);o.module.exports=e.apply(o)}else void 0!==o.define&&"function"===o.define&&o.define.amd?define("base64",t||[],e):o.base64=e.apply(o)}(0,function(r){var e=r||this.utf8,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=e.encode(r);for(var t,n,i,d,f,a,h,c="",u=0;u<r.length;)d=(t=r.charCodeAt(u++))>>2,f=(3&t)<<4|(n=r.charCodeAt(u++))>>4,a=(15&n)<<2|(i=r.charCodeAt(u++))>>6,h=63&i,isNaN(n)?a=h=64:isNaN(i)&&(h=64),c+=o.charAt(d)+o.charAt(f)+o.charAt(a)+o.charAt(h);return c},decode:function(r){if(void 0===e)throw{error:"MissingMethod",message:"UTF8 Module is missing."};if("string"!=typeof r)return r;r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var t,n,i,d,f,a,h="",c=0;c<r.length;)t=o.indexOf(r.charAt(c++))<<2|(d=o.indexOf(r.charAt(c++)))>>4,n=(15&d)<<4|(f=o.indexOf(r.charAt(c++)))>>2,i=(3&f)<<6|(a=o.indexOf(r.charAt(c++))),h+=String.fromCharCode(t),64!=f&&(h+=String.fromCharCode(n)),64!=a&&(h+=String.fromCharCode(i));return e.decode(h)}}},this,["utf8"]);
@@ -0,0 +1,14 @@
{
"tiddlers": [
{
"file": "base64-utf8.module.min.js",
"fields": {
"type": "application/javascript",
"title": "$:/core/modules/utils/base64-utf8/base64-utf8.module.js",
"module-type": "library"
},
"prefix": "(function(){",
"suffix": "}).call(exports);"
}
]
}
+14 -5
View File
@@ -136,22 +136,31 @@ exports.getBoundingPageRect = function(element) {
Saves a named password in the browser
*/
exports.savePassword = function(name,password) {
var done = false;
try {
if(window.localStorage) {
localStorage.setItem("tw5-password-" + name,password);
}
window.localStorage.setItem("tw5-password-" + name,password);
done = true;
} catch(e) {
}
if(!done) {
$tw.savedPasswords = $tw.savedPasswords || Object.create(null);
$tw.savedPasswords[name] = password;
}
};
/*
Retrieve a named password from the browser
*/
exports.getPassword = function(name) {
var value;
try {
return window.localStorage ? localStorage.getItem("tw5-password-" + name) : "";
value = window.localStorage.getItem("tw5-password-" + name);
} catch(e) {
return "";
}
if(value !== undefined) {
return value;
} else {
return ($tw.savedPasswords || Object.create(null))[name] || "";
}
};
+3 -3
View File
@@ -17,7 +17,7 @@ A quick and dirty HTTP function; to be refactored later. Options are:
url: URL to retrieve
headers: hashmap of headers to send
type: GET, PUT, POST etc
callback: function invoked with (err,data)
callback: function invoked with (err,data,xhr)
returnProp: string name of the property to return as first argument of callback
*/
exports.httpRequest = function(options) {
@@ -48,7 +48,7 @@ exports.httpRequest = function(options) {
return;
}
// Something went wrong
options.callback($tw.language.getString("Error/XMLHttpRequest") + ": " + this.status);
options.callback($tw.language.getString("Error/XMLHttpRequest") + ": " + this.status,null,this);
}
};
// Make the request
@@ -67,7 +67,7 @@ exports.httpRequest = function(options) {
try {
request.send(data);
} catch(e) {
options.callback(e);
options.callback(e,null,this);
}
return request;
};
+1 -1
View File
@@ -30,7 +30,7 @@ Modal.prototype.display = function(title,options) {
options = options || {};
this.srcDocument = options.variables && (options.variables.rootwindow === "true" ||
options.variables.rootwindow === "yes") ? document :
(options.event.event ? options.event.event.target.ownerDocument : document);
(options.event.event && options.event.event.target ? options.event.event.target.ownerDocument : document);
this.srcWindow = this.srcDocument.defaultView;
var self = this,
refreshHandler,
+35 -5
View File
@@ -120,7 +120,8 @@ Popup.prototype.show = function(options) {
this.popups.push({
title: options.title,
wiki: options.wiki,
domNode: options.domNode
domNode: options.domNode,
noStateReference: options.noStateReference
});
}
// Set the state tiddler
@@ -148,17 +149,46 @@ Popup.prototype.show = function(options) {
}
};
/*
Detect if a Popup contains an input field that has focus
Returns true or false
*/
Popup.prototype.detectInputWithinPopup = function(node) {
var withinPopup = false,
currNode = node;
for(var i=0; i<this.popups.length; i++) {
var popup = (this.popups[i] && this.popups[i].domNode) ? this.popups[i].domNode : null;
while(node && popup) {
if(node === popup || (node.classList && (node.classList.contains("tc-popup-keep") || (node !== currNode && node.classList.contains("tc-popup-handle"))))) {
withinPopup = true;
}
node = node.parentNode;
}
}
return withinPopup;
};
/*
Cancel all popups at or above a specified level or DOM node
level: popup level to cancel (0 cancels all popups)
*/
Popup.prototype.cancel = function(level) {
Popup.prototype.cancel = function(level,focusedInputNode) {
var numPopups = this.popups.length;
level = Math.max(0,Math.min(level,numPopups));
for(var t=level; t<numPopups; t++) {
var popup = this.popups.pop();
if(popup.title) {
popup.wiki.deleteTiddler(popup.title);
var inputWithinPopup;
if(focusedInputNode) {
inputWithinPopup = this.detectInputWithinPopup(focusedInputNode);
}
if(!inputWithinPopup) {
var popup = this.popups.pop();
if(popup.title) {
if(popup.noStateReference) {
popup.wiki.deleteTiddler(popup.title);
} else {
popup.wiki.deleteTiddler($tw.utils.parseTextReference(popup.title).title);
}
}
}
}
if(this.popups.length === 0) {
+4
View File
@@ -33,6 +33,10 @@ var PageScroller = function() {
};
};
PageScroller.prototype.isScrolling = function() {
return this.idRequestFrame !== null;
}
PageScroller.prototype.cancelScroll = function(srcWindow) {
if(this.idRequestFrame) {
this.cancelAnimationFrame.call(srcWindow,this.idRequestFrame);
+23 -5
View File
@@ -45,10 +45,28 @@ var TW_Element = function(tag,namespace) {
this.attributes = {};
this.isRaw = false;
this.children = [];
this.style = {};
this._style = {};
this.namespaceURI = namespace || "http://www.w3.org/1999/xhtml";
};
Object.defineProperty(TW_Element.prototype, "style", {
get: function() {
return this._style;
},
set: function(str) {
var self = this;
str = str || "";
$tw.utils.each(str.split(";"),function(declaration) {
var parts = declaration.split(":"),
name = $tw.utils.trim(parts[0]),
value = $tw.utils.trim(parts[1]);
if(name && value) {
self._style[$tw.utils.convertStyleNameToPropertyName(name)] = value;
}
});
}
});
Object.defineProperty(TW_Element.prototype, "nodeType", {
get: function() {
return 1;
@@ -169,13 +187,13 @@ Object.defineProperty(TW_Element.prototype, "outerHTML", {
}
}
}
if(this.style) {
if(this._style) {
var style = [];
for(var s in this.style) {
style.push(s + ":" + this.style[s] + ";");
for(var s in this._style) {
style.push($tw.utils.convertPropertyNameToStyleName(s) + ":" + this._style[s] + ";");
}
if(style.length > 0) {
output.push(" style=\"",style.join(""),"\"")
output.push(" style=\"",style.join(""),"\"");
}
}
output.push(">");
+165
View File
@@ -181,4 +181,169 @@ exports.deleteEmptyDirs = function(dirpath,callback) {
});
};
/*
Create a fileInfo object for saving a tiddler:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
Options include:
directory: absolute path of root directory to which we are saving
pathFilters: optional array of filters to be used to generate the base path
wiki: optional wiki for evaluating the pathFilters
*/
exports.generateTiddlerFileInfo = function(tiddler,options) {
var fileInfo = {};
// Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace
var hasUnsafeFields = false;
$tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) {
if(fieldName !== "text") {
hasUnsafeFields = hasUnsafeFields || /[\x00-\x1F]/mg.test(value);
hasUnsafeFields = hasUnsafeFields || ($tw.utils.trim(value) !== value);
}
});
// Check for field values
if(hasUnsafeFields) {
// Save as a JSON file
fileInfo.type = "application/json";
fileInfo.hasMetaFile = false;
} else {
// Save as a .tid or a text/binary file plus a .meta file
var tiddlerType = tiddler.fields.type || "text/vnd.tiddlywiki";
if(tiddlerType === "text/vnd.tiddlywiki") {
// Save as a .tid file
fileInfo.type = "application/x-tiddler";
fileInfo.hasMetaFile = false;
} else {
// Save as a text/binary file and a .meta file
fileInfo.type = tiddlerType;
fileInfo.hasMetaFile = true;
}
}
// Take the file extension from the tiddler content type
var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""};
// Generate the filepath
fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{
extension: contentTypeInfo.extension,
directory: options.directory,
pathFilters: options.pathFilters,
wiki: options.wiki
});
return fileInfo;
};
/*
Generate the filepath for saving a tiddler
Options include:
extension: file extension to be added the finished filepath
directory: absolute path of root directory to which we are saving
pathFilters: optional array of filters to be used to generate the base path
wiki: optional wiki for evaluating the pathFilters
*/
exports.generateTiddlerFilepath = function(title,options) {
var self = this,
directory = options.directory || "",
extension = options.extension || "",
filepath;
// Check if any of the pathFilters applies
if(options.pathFilters && options.wiki) {
$tw.utils.each(options.pathFilters,function(filter) {
if(!filepath) {
var source = options.wiki.makeTiddlerIterator([title]),
result = options.wiki.filterTiddlers(filter,null,source);
if(result.length > 0) {
filepath = result[0];
}
}
});
}
// If not, generate a base pathname
if(!filepath) {
filepath = title;
// If the filepath already ends in the extension then remove it
if(filepath.substring(filepath.length - extension.length) === extension) {
filepath = filepath.substring(0,filepath.length - extension.length);
}
// Remove any forward or backward slashes so we don't create directories
filepath = filepath.replace(/\/|\\/g,"_");
}
// Don't let the filename start with a dot because such files are invisible on *nix
filepath = filepath.replace(/^\./g,"_");
// Remove any characters that can't be used in cross-platform filenames
filepath = $tw.utils.transliterate(filepath.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_"));
// Truncate the filename if it is too long
if(filepath.length > 200) {
filepath = filepath.substr(0,200);
}
// If the resulting filename is blank (eg because the title is just punctuation characters)
if(!filepath) {
// ...then just use the character codes of the title
filepath = "";
$tw.utils.each(title.split(""),function(char) {
if(filepath) {
filepath += "-";
}
filepath += char.charCodeAt(0).toString();
});
}
// Add a uniquifier if the file already exists
var fullPath,
count = 0;
do {
fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension);
count++;
} while(fs.existsSync(fullPath));
// Return the full path to the file
return fullPath;
};
/*
Save a tiddler to a file described by the fileInfo:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
*/
exports.saveTiddlerToFile = function(tiddler,fileInfo,callback) {
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
if(fileInfo.hasMetaFile) {
// Save the tiddler as a separate body and meta file
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
fs.writeFile(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding,function(err) {
if(err) {
return callback(err);
}
fs.writeFile(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8",callback);
});
} else {
// Save the tiddler as a self contained templated file
if(fileInfo.type === "application/x-tiddler") {
fs.writeFile(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8",callback);
} else {
fs.writeFile(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8",callback);
}
}
};
/*
Save a tiddler to a file described by the fileInfo:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler)
hasMetaFile: true if the file also has a companion .meta file
*/
exports.saveTiddlerToFileSync = function(tiddler,fileInfo) {
$tw.utils.createDirectory(path.dirname(fileInfo.filepath));
if(fileInfo.hasMetaFile) {
// Save the tiddler as a separate body and meta file
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
fs.writeFileSync(fileInfo.filepath,tiddler.fields.text,typeInfo.encoding);
fs.writeFileSync(fileInfo.filepath + ".meta",tiddler.getFieldStringBlock({exclude: ["text","bag"]}),"utf8");
} else {
// Save the tiddler as a self contained templated file
if(fileInfo.type === "application/x-tiddler") {
fs.writeFileSync(fileInfo.filepath,tiddler.getFieldStringBlock({exclude: ["text","bag"]}) + (!!tiddler.fields.text ? "\n\n" + tiddler.fields.text : ""),"utf8");
} else {
fs.writeFileSync(fileInfo.filepath,JSON.stringify([tiddler.getFieldStrings({exclude: ["bag"]})],null,$tw.config.preferences.jsonSpaces),"utf8");
}
}
};
})();
+7
View File
@@ -33,6 +33,13 @@ Logger.prototype.log = function(/* args */) {
}
};
/*
Log a structure as a table
*/
Logger.prototype.table = function(value) {
(console.table || console.log)(value);
};
/*
Alert a message
*/
+37 -8
View File
@@ -14,10 +14,17 @@ Performance measurement.
function Performance(enabled) {
this.enabled = !!enabled;
this.measures = {}; // Hashmap of current values of measurements
this.measures = {}; // Hashmap by measurement name of {time:, invocations:}
this.logger = new $tw.utils.Logger("performance");
this.showGreeting();
}
Performance.prototype.showGreeting = function() {
if($tw.browser) {
this.logger.log("Execute $tw.perf.log(); to see filter execution timings");
}
};
/*
Wrap performance reporting around a top level function
*/
@@ -25,13 +32,9 @@ Performance.prototype.report = function(name,fn) {
var self = this;
if(this.enabled) {
return function() {
self.measures = {};
var startTime = $tw.utils.timer(),
result = fn.apply(this,arguments);
self.logger.log(name + ": " + $tw.utils.timer(startTime).toFixed(2) + "ms");
for(var m in self.measures) {
self.logger.log("+" + m + ": " + self.measures[m].toFixed(2) + "ms");
}
return result;
};
} else {
@@ -39,6 +42,29 @@ Performance.prototype.report = function(name,fn) {
}
};
Performance.prototype.log = function() {
var self = this,
totalTime = 0,
orderedMeasures = Object.keys(this.measures).sort(function(a,b) {
if(self.measures[a].time > self.measures[b].time) {
return -1;
} else if (self.measures[a].time < self.measures[b].time) {
return + 1;
} else {
return 0;
}
});
$tw.utils.each(orderedMeasures,function(name) {
totalTime += self.measures[name].time;
});
var results = []
$tw.utils.each(orderedMeasures,function(name) {
var measure = self.measures[name];
results.push({name: name,invocations: measure.invocations, avgTime: measure.time / measure.invocations, totalTime: measure.time, percentTime: (measure.time / totalTime) * 100})
});
self.logger.table(results);
};
/*
Wrap performance measurements around a subfunction
*/
@@ -47,9 +73,12 @@ Performance.prototype.measure = function(name,fn) {
if(this.enabled) {
return function() {
var startTime = $tw.utils.timer(),
result = fn.apply(this,arguments),
value = self.measures[name] || 0;
self.measures[name] = value + $tw.utils.timer(startTime);
result = fn.apply(this,arguments);
if(!(name in self.measures)) {
self.measures[name] = {time: 0, invocations: 0};
}
self.measures[name].time += $tw.utils.timer(startTime);
self.measures[name].invocations++;
return result;
};
} else {
+25 -64
View File
@@ -12,6 +12,8 @@ Various static utility functions.
/*global $tw: false */
"use strict";
var base64utf8 = require("$:/core/modules/utils/base64-utf8/base64-utf8.module.js");
/*
Display a message, in colour if we're on a terminal
*/
@@ -92,6 +94,20 @@ exports.trim = function(str) {
}
};
/*
Convert a string to sentence case (ie capitalise first letter)
*/
exports.toSentenceCase = function(str) {
return (str || "").replace(/^\S/, function(c) {return c.toUpperCase();});
}
/*
Convert a string to title case (ie capitalise each initial letter)
*/
exports.toTitleCase = function(str) {
return (str || "").replace(/(^|\s)\S/g, function(c) {return c.toUpperCase();});
}
/*
Find the line break preceding a given position in a string
Returns position immediately after that line break, or the start of the string
@@ -132,23 +148,6 @@ exports.count = function(object) {
return Object.keys(object || {}).length;
};
/*
Check if an array is equal by value and by reference.
*/
exports.isArrayEqual = function(array1,array2) {
if(array1 === array2) {
return true;
}
array1 = array1 || [];
array2 = array2 || [];
if(array1.length !== array2.length) {
return false;
}
return array1.every(function(value,index) {
return value === array2[index];
});
};
/*
Determine whether an array-item is an object-property
*/
@@ -161,46 +160,6 @@ exports.hopArray = function(object,array) {
return false;
};
/*
Push entries onto an array, removing them first if they already exist in the array
array: array to modify (assumed to be free of duplicates)
value: a single value to push or an array of values to push
*/
exports.pushTop = function(array,value) {
var t,p;
if($tw.utils.isArray(value)) {
// Remove any array entries that are duplicated in the new values
if(value.length !== 0) {
if(array.length !== 0) {
if(value.length < array.length) {
for(t=0; t<value.length; t++) {
p = array.indexOf(value[t]);
if(p !== -1) {
array.splice(p,1);
}
}
} else {
for(t=array.length-1; t>=0; t--) {
p = value.indexOf(array[t]);
if(p !== -1) {
array.splice(t,1);
}
}
}
}
// Push the values on top of the main array
array.push.apply(array,value);
}
} else {
p = array.indexOf(value);
if(p !== -1) {
array.splice(p,1);
}
array.push(value);
}
return array;
};
/*
Remove entries from an array
array: array to modify
@@ -708,7 +667,7 @@ exports.extractVersionInfo = function() {
Get the animation duration in ms
*/
exports.getAnimationDuration = function() {
return parseInt($tw.wiki.getTiddlerText("$:/config/AnimationDuration","400"),10);
return parseInt($tw.wiki.getTiddlerText("$:/config/AnimationDuration","400"),10) || 0;
};
/*
@@ -726,12 +685,14 @@ exports.hashString = function(str) {
Decode a base64 string
*/
exports.base64Decode = function(string64) {
if($tw.browser) {
// TODO
throw "$tw.utils.base64Decode() doesn't work in the browser";
} else {
return Buffer.from(string64,"base64").toString();
}
return base64utf8.base64.decode.call(base64utf8,string64);
};
/*
Encode a string to base64
*/
exports.base64Encode = function(string64) {
return base64utf8.base64.encode.call(base64utf8,string64);
};
/*
@@ -37,6 +37,7 @@ Compute the internal state of the widget
CreateTiddlerWidget.prototype.execute = function() {
this.actionBaseTitle = this.getAttribute("$basetitle");
this.actionSaveTitle = this.getAttribute("$savetitle");
this.actionSaveDraftTitle = this.getAttribute("$savedrafttitle");
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
};
@@ -73,6 +74,9 @@ CreateTiddlerWidget.prototype.invokeAction = function(triggeringWidget,event) {
if(this.actionSaveTitle) {
this.wiki.setTextReference(this.actionSaveTitle,title,this.getVariable("currentTiddler"));
}
if(this.actionSaveDraftTitle) {
this.wiki.setTextReference(this.actionSaveDraftTitle,this.wiki.generateDraftTitle(title),this.getVariable("currentTiddler"));
}
return true; // Action was invoked
};
+4
View File
@@ -156,6 +156,9 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
if(this.checkboxActions) {
this.invokeActionString(this.checkboxActions,this,event);
}
if(this.checkboxCheckActions && checked) {
this.invokeActionString(this.checkboxCheckActions,this,event);
}
if(this.checkboxUncheckActions && !checked) {
this.invokeActionString(this.checkboxUncheckActions,this,event);
}
@@ -167,6 +170,7 @@ Compute the internal state of the widget
CheckboxWidget.prototype.execute = function() {
// Get the parameters from the attributes
this.checkboxActions = this.getAttribute("actions");
this.checkboxCheckActions = this.getAttribute("checkactions");
this.checkboxUncheckActions = this.getAttribute("uncheckactions");
this.checkboxTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
this.checkboxTag = this.getAttribute("tag");
+6 -1
View File
@@ -42,7 +42,8 @@ DropZoneWidget.prototype.render = function(parent,nextSibling) {
{name: "dragover", handlerObject: this, handlerMethod: "handleDragOverEvent"},
{name: "dragleave", handlerObject: this, handlerMethod: "handleDragLeaveEvent"},
{name: "drop", handlerObject: this, handlerMethod: "handleDropEvent"},
{name: "paste", handlerObject: this, handlerMethod: "handlePasteEvent"}
{name: "paste", handlerObject: this, handlerMethod: "handlePasteEvent"},
{name: "dragend", handlerObject: this, handlerMethod: "handleDragEndEvent"}
]);
domNode.addEventListener("click",function (event) {
},false);
@@ -103,6 +104,10 @@ DropZoneWidget.prototype.handleDragLeaveEvent = function(event) {
this.leaveDrag(event);
};
DropZoneWidget.prototype.handleDragEndEvent = function(event) {
$tw.utils.removeClass(this.domNodes[0],"tc-dragover");
};
DropZoneWidget.prototype.handleDropEvent = function(event) {
var self = this,
readFileCallback = function(tiddlerFieldsArray) {
+19 -14
View File
@@ -14,7 +14,8 @@ Edit-bitmap widget
// Default image sizes
var DEFAULT_IMAGE_WIDTH = 600,
DEFAULT_IMAGE_HEIGHT = 370;
DEFAULT_IMAGE_HEIGHT = 370,
DEFAULT_IMAGE_TYPE = "image/png";
// Configuration tiddlers
var LINE_WIDTH_TITLE = "$:/config/BitmapEditor/LineWidth",
@@ -154,7 +155,13 @@ EditBitmapWidget.prototype.loadCanvas = function() {
self.refreshToolbar();
};
// Get the current bitmap into an image object
currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
if(tiddler && tiddler.fields.type && tiddler.fields.text) {
currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
} else {
currImage.width = DEFAULT_IMAGE_WIDTH;
currImage.height = DEFAULT_IMAGE_HEIGHT;
currImage.onerror();
}
};
EditBitmapWidget.prototype.initCanvas = function(canvas,width,height,image) {
@@ -319,18 +326,16 @@ EditBitmapWidget.prototype.strokeEnd = function() {
};
EditBitmapWidget.prototype.saveChanges = function() {
var tiddler = this.wiki.getTiddler(this.editTitle);
if(tiddler) {
// data URIs look like "data:<type>;base64,<text>"
var dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),
posColon = dataURL.indexOf(":"),
posSemiColon = dataURL.indexOf(";"),
posComma = dataURL.indexOf(","),
type = dataURL.substring(posColon+1,posSemiColon),
text = dataURL.substring(posComma+1);
var update = {type: type, text: text};
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));
}
var tiddler = this.wiki.getTiddler(this.editTitle) || new $tw.Tiddler({title: this.editTitle,type: DEFAULT_IMAGE_TYPE});
// data URIs look like "data:<type>;base64,<text>"
var dataURL = this.canvasDomNode.toDataURL(tiddler.fields.type),
posColon = dataURL.indexOf(":"),
posSemiColon = dataURL.indexOf(";"),
posComma = dataURL.indexOf(","),
type = dataURL.substring(posColon+1,posSemiColon),
text = dataURL.substring(posComma+1);
var update = {type: type, text: text};
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getModificationFields(),tiddler,update,this.wiki.getCreationFields()));
};
exports["edit-bitmap"] = EditBitmapWidget;
+16 -1
View File
@@ -57,6 +57,10 @@ EditShortcutWidget.prototype.render = function(parent,nextSibling) {
// Link into the DOM
parent.insertBefore(this.inputNode,nextSibling);
this.domNodes.push(this.inputNode);
// Focus the input Node if focus === "yes" or focus === "true"
if(this.shortcutFocus === "yes" || this.shortcutFocus === "true") {
this.focus();
}
};
/*
@@ -72,6 +76,7 @@ EditShortcutWidget.prototype.execute = function() {
this.shortcutStyle = this.getAttribute("style");
this.shortcutTooltip = this.getAttribute("tooltip");
this.shortcutAriaLabel = this.getAttribute("aria-label");
this.shortcutFocus = this.getAttribute("focus");
};
/*
@@ -118,12 +123,22 @@ EditShortcutWidget.prototype.handleKeydownEvent = function(event) {
}
};
/*
focus the input node
*/
EditShortcutWidget.prototype.focus = function() {
if(this.inputNode.focus && this.inputNode.select) {
this.inputNode.focus();
this.inputNode.select();
}
};
/*
Selectively refreshes the widget if needed. Returns true if the widget needed re-rendering
*/
EditShortcutWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.placeholder || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.style || changedAttributes.tooltip || changedAttributes["aria-label"]) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.placeholder || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.style || changedAttributes.tooltip || changedAttributes["aria-label"] || changedAttributes.focus) {
this.refreshSelf();
return true;
} else if(changedTiddlers[this.shortcutTiddler]) {
+5 -3
View File
@@ -46,6 +46,7 @@ EditWidget.prototype.execute = function() {
this.editIndex = this.getAttribute("index");
this.editClass = this.getAttribute("class");
this.editPlaceholder = this.getAttribute("placeholder");
this.editTabIndex = this.getAttribute("tabindex");
// Choose the appropriate edit widget
this.editorType = this.getEditorType();
// Make the child widgets
@@ -56,7 +57,8 @@ EditWidget.prototype.execute = function() {
field: {type: "string", value: this.editField},
index: {type: "string", value: this.editIndex},
"class": {type: "string", value: this.editClass},
"placeholder": {type: "string", value: this.editPlaceholder}
"placeholder": {type: "string", value: this.editPlaceholder},
"tabindex": {type: "string", value: this.editTabIndex}
},
children: this.parseTreeNode.children
}]);
@@ -90,11 +92,11 @@ 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 || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) {
this.refreshSelf();
return true;
} else {
return this.refreshChildren(changedTiddlers);
return this.refreshChildren(changedTiddlers);
}
};
+6 -6
View File
@@ -73,13 +73,13 @@ Compute the internal state of the widget
KeyboardWidget.prototype.execute = function() {
var self = this;
// Get attributes
this.actions = this.getAttribute("actions");
this.message = this.getAttribute("message");
this.param = this.getAttribute("param");
this.key = this.getAttribute("key");
this.tag = this.getAttribute("tag");
this.actions = this.getAttribute("actions","");
this.message = this.getAttribute("message","");
this.param = this.getAttribute("param","");
this.key = this.getAttribute("key","");
this.tag = this.getAttribute("tag","");
this.keyInfoArray = $tw.keyboardManager.parseKeyDescriptors(this.key);
this["class"] = this.getAttribute("class");
this["class"] = this.getAttribute("class","");
if(this.key.substr(0,2) === "((" && this.key.substr(-2,2) === "))") {
this.shortcutTiddlers = [];
var name = this.key.substring(2,this.key.length -2);
+8 -1
View File
@@ -183,7 +183,14 @@ LinkWidget.prototype.execute = function() {
this.isShadow = this.wiki.isShadowTiddler(this.to);
this.hideMissingLinks = (this.getVariable("tv-show-missing-links") || "yes") === "no";
// Make the child widgets
this.makeChildWidgets();
var templateTree;
if(this.parseTreeNode.children && this.parseTreeNode.children.length > 0) {
templateTree = this.parseTreeNode.children;
} else {
// Default template is a link to the title
templateTree = [{type: "text", text: this.to}];
}
this.makeChildWidgets(templateTree);
};
/*
+38 -36
View File
@@ -84,39 +84,50 @@ NavigatorWidget.prototype.getStoryList = function() {
};
NavigatorWidget.prototype.saveStoryList = function(storyList) {
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
this.wiki.addTiddler(new $tw.Tiddler(
{title: this.storyTitle},
storyTiddler,
{list: storyList}
));
if(this.storyTitle) {
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
this.wiki.addTiddler(new $tw.Tiddler(
{title: this.storyTitle},
storyTiddler,
{list: storyList}
));
}
};
NavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {
var p = storyList.indexOf(title);
while(p !== -1) {
storyList.splice(p,1);
p = storyList.indexOf(title);
if(storyList) {
var p = storyList.indexOf(title);
while(p !== -1) {
storyList.splice(p,1);
p = storyList.indexOf(title);
}
}
};
NavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {
var pos = storyList.indexOf(oldTitle);
if(pos !== -1) {
storyList[pos] = newTitle;
do {
pos = storyList.indexOf(oldTitle,pos + 1);
if(pos !== -1) {
storyList.splice(pos,1);
}
} while(pos !== -1);
} else {
storyList.splice(0,0,newTitle);
if(storyList) {
var pos = storyList.indexOf(oldTitle);
if(pos !== -1) {
storyList[pos] = newTitle;
do {
pos = storyList.indexOf(oldTitle,pos + 1);
if(pos !== -1) {
storyList.splice(pos,1);
}
} while(pos !== -1);
} else {
storyList.splice(0,0,newTitle);
}
}
};
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
this.wiki.addToStory(title,fromTitle,this.storyTitle,{openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")});
if(this.storyTitle) {
this.wiki.addToStory(title,fromTitle,this.storyTitle,{
openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"),
openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top")
});
}
};
/*
@@ -279,15 +290,7 @@ NavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {
Generate a title for the draft of a given tiddler
*/
NavigatorWidget.prototype.generateDraftTitle = function(title) {
var c = 0,
draftTitle,
username = this.wiki.getTiddlerText("$:/status/UserName"),
attribution = username ? " by " + username : "";
do {
draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'" + attribution;
c++;
} while(this.wiki.tiddlerExists(draftTitle));
return draftTitle;
return this.wiki.generateDraftTitle(title);
};
// Take a tiddler out of edit mode, saving the changes
@@ -466,14 +469,14 @@ NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
},this.wiki.getModificationFields());
this.wiki.addTiddler(draftTiddler);
// Update the story to insert the new draft at the top and remove any existing tiddler
if(storyList.indexOf(draftTitle) === -1) {
if(storyList && storyList.indexOf(draftTitle) === -1) {
var slot = storyList.indexOf(event.navigateFromTitle);
if(slot === -1) {
slot = this.getAttribute("openLinkFromOutsideRiver","top") === "bottom" ? storyList.length - 1 : slot;
}
storyList.splice(slot + 1,0,draftTitle);
}
if(storyList.indexOf(title) !== -1) {
if(storyList && storyList.indexOf(title) !== -1) {
storyList.splice(storyList.indexOf(title),1);
}
this.saveStoryList(storyList);
@@ -529,7 +532,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
var storyList = this.getStoryList(),
history = [];
// Add it to the story
if(storyList.indexOf(IMPORT_TITLE) === -1) {
if(storyList && storyList.indexOf(IMPORT_TITLE) === -1) {
storyList.unshift(IMPORT_TITLE);
}
// And to history
@@ -590,7 +593,7 @@ NavigatorWidget.prototype.handleFoldOtherTiddlersEvent = function(event) {
NavigatorWidget.prototype.handleFoldAllTiddlersEvent = function(event) {
var self = this,
paramObject = event.paramObject || {},
prefix = paramObject.foldedStatePrefix;
prefix = paramObject.foldedStatePrefix || "$:/state/folded/";
$tw.utils.each(this.getStoryList(),function(title) {
self.wiki.setText(prefix + title,"text",null,"hide");
});
@@ -606,7 +609,6 @@ NavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {
};
NavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {
event = $tw.hooks.invokeHook("th-renaming-tiddler", event);
var paramObject = event.paramObject || {},
from = paramObject.from || event.tiddlerTitle,
to = paramObject.to;
+40 -20
View File
@@ -56,32 +56,39 @@ RevealWidget.prototype.render = function(parent,nextSibling) {
RevealWidget.prototype.positionPopup = function(domNode) {
domNode.style.position = "absolute";
domNode.style.zIndex = "1000";
var left,top;
switch(this.position) {
case "left":
domNode.style.left = Math.max(0, this.popup.left - domNode.offsetWidth) + "px";
domNode.style.top = this.popup.top + "px";
left = this.popup.left - domNode.offsetWidth;
top = this.popup.top;
break;
case "above":
domNode.style.left = this.popup.left + "px";
domNode.style.top = Math.max(0, this.popup.top - domNode.offsetHeight) + "px";
left = this.popup.left;
top = this.popup.top - domNode.offsetHeight;
break;
case "aboveright":
domNode.style.left = (this.popup.left + this.popup.width) + "px";
domNode.style.top = Math.max(0, this.popup.top + this.popup.height - domNode.offsetHeight) + "px";
left = this.popup.left + this.popup.width;
top = this.popup.top + this.popup.height - domNode.offsetHeight;
break;
case "right":
domNode.style.left = (this.popup.left + this.popup.width) + "px";
domNode.style.top = this.popup.top + "px";
left = this.popup.left + this.popup.width;
top = this.popup.top;
break;
case "belowleft":
domNode.style.left = Math.max(0, this.popup.left + this.popup.width - domNode.offsetWidth) + "px";
domNode.style.top = (this.popup.top + this.popup.height) + "px";
left = this.popup.left + this.popup.width - domNode.offsetWidth;
top = this.popup.top + this.popup.height;
break;
default: // Below
domNode.style.left = this.popup.left + "px";
domNode.style.top = (this.popup.top + this.popup.height) + "px";
left = this.popup.left;
top = this.popup.top + this.popup.height;
break;
}
if(!this.positionAllowNegative) {
left = Math.max(0,left);
top = Math.max(0,top);
}
domNode.style.left = left + "px";
domNode.style.top = top + "px";
};
/*
@@ -94,6 +101,7 @@ RevealWidget.prototype.execute = function() {
this.type = this.getAttribute("type");
this.text = this.getAttribute("text");
this.position = this.getAttribute("position");
this.positionAllowNegative = this.getAttribute("positionAllowNegative") === "yes";
this["class"] = this.getAttribute("class","");
this.style = this.getAttribute("style","");
this["default"] = this.getAttribute("default","");
@@ -118,10 +126,22 @@ Read the state tiddler
*/
RevealWidget.prototype.readState = function() {
// Read the information from the state tiddler
var state = this.stateTitle ? (this.stateField ? this.wiki.getTiddler(this.stateTitle).getFieldString(this.stateField) :
(this.stateIndex ? this.wiki.extractTiddlerDataItem(this.stateTitle,this.stateIndex) :
this.wiki.getTiddlerText(this.stateTitle))) || this["default"] || this.getVariable("currentTiddler") :
(this.stateTiddlerTitle ? this.wiki.getTextReference(this.state,this["default"],this.getVariable("currentTiddler")) : this["default"]);
var state,
defaultState = this["default"];
if(this.stateTitle) {
var stateTitleTiddler = this.wiki.getTiddler(this.stateTitle);
if(this.stateField) {
state = stateTitleTiddler ? stateTitleTiddler.getFieldString(this.stateField) || defaultState : defaultState;
} else if(this.stateIndex) {
state = stateTitleTiddler ? this.wiki.extractTiddlerDataItem(this.stateTitle,this.stateIndex) || defaultState : defaultState;
} else if(stateTitleTiddler) {
state = this.wiki.getTiddlerText(this.stateTitle) || defaultState;
} else {
state = defaultState;
}
} else {
state = this.stateTiddlerTitle ? this.wiki.getTextReference(this.state,this["default"],this.getVariable("currentTiddler")) : this["default"];
}
if(state === null) {
state = this["default"];
}
@@ -130,10 +150,10 @@ RevealWidget.prototype.readState = function() {
this.readPopupState(state);
break;
case "match":
this.isOpen = !!(this.compareStateText(state) == 0);
this.isOpen = this.text === state;
break;
case "nomatch":
this.isOpen = !(this.compareStateText(state) == 0);
this.isOpen = this.text !== state;
break;
case "lt":
this.isOpen = !!(this.compareStateText(state) < 0);
@@ -179,13 +199,13 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/
RevealWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {
if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) {
this.refreshSelf();
return true;
} else {
var currentlyOpen = this.isOpen;
this.readState();
if(this.isOpen !== currentlyOpen || (this.stateTiddlerTitle && changedTiddlers[this.stateTiddlerTitle])) {
if(this.isOpen !== currentlyOpen) {
if(this.retain === "yes") {
this.updateState();
} else {
+5 -1
View File
@@ -145,6 +145,7 @@ SelectWidget.prototype.execute = function() {
this.selectDefault = this.getAttribute("default");
this.selectMultiple = this.getAttribute("multiple", false);
this.selectSize = this.getAttribute("size");
this.selectTooltip = this.getAttribute("tooltip");
// Make the child widgets
var selectNode = {
type: "element",
@@ -160,6 +161,9 @@ SelectWidget.prototype.execute = function() {
if(this.selectSize) {
$tw.utils.addAttributeToParseTreeNode(selectNode,"size",this.selectSize);
}
if(this.selectTooltip) {
$tw.utils.addAttributeToParseTreeNode(selectNode,"title",this.selectTooltip);
}
this.makeChildWidgets([selectNode]);
};
@@ -169,7 +173,7 @@ 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.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex) {
if(changedAttributes.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex || changedAttributes.selectTooltip) {
this.refreshSelf();
return true;
// If the target tiddler value has changed, just update setting and refresh the children
+27 -10
View File
@@ -22,15 +22,17 @@ Options include:
document: optional document object to use instead of global document
*/
var Widget = function(parseTreeNode,options) {
if(arguments.length > 0) {
this.initialise(parseTreeNode,options);
}
this.initialise(parseTreeNode,options);
};
/*
Initialise widget properties. These steps are pulled out of the constructor so that we can reuse them in subclasses
*/
Widget.prototype.initialise = function(parseTreeNode,options) {
// Bail if parseTreeNode is undefined, meaning that the widget constructor was called without any arguments so that it can be subclassed
if(parseTreeNode === undefined) {
return;
}
options = options || {};
// Save widget info
this.parseTreeNode = parseTreeNode;
@@ -46,7 +48,21 @@ Widget.prototype.initialise = function(parseTreeNode,options) {
this.eventListeners = {};
// Hashmap of the widget classes
if(!this.widgetClasses) {
// Get widget classes
Widget.prototype.widgetClasses = $tw.modules.applyMethods("widget");
// Process any subclasses
$tw.modules.forEachModuleOfType("widget-subclass",function(title,module) {
if(module.baseClass) {
var baseClass = Widget.prototype.widgetClasses[module.baseClass];
if(!baseClass) {
throw "Module '" + title + "' is attemping to extend a non-existent base class '" + module.baseClass + "'";
}
var subClass = module.constructor;
subClass.prototype = new baseClass();
$tw.utils.extend(subClass.prototype,module.prototype);
Widget.prototype.widgetClasses[module.name || module.baseClass] = subClass;
}
});
}
};
@@ -369,9 +385,10 @@ Widget.prototype.previousSibling = function() {
Render the children of this widget into the DOM
*/
Widget.prototype.renderChildren = function(parent,nextSibling) {
$tw.utils.each(this.children,function(childWidget) {
childWidget.render(parent,nextSibling);
});
var children = this.children;
for(var i = 0; i < children.length; i++) {
children[i].render(parent,nextSibling);
};
};
/*
@@ -439,11 +456,11 @@ Widget.prototype.refreshSelf = function() {
Refresh all the children of a widget
*/
Widget.prototype.refreshChildren = function(changedTiddlers) {
var self = this,
var children = this.children,
refreshed = false;
$tw.utils.each(this.children,function(childWidget) {
refreshed = childWidget.refresh(changedTiddlers) || refreshed;
});
for (var i = 0; i < children.length; i++) {
refreshed = children[i].refresh(changedTiddlers) || refreshed;
}
return refreshed;
};
+2 -2
View File
@@ -44,8 +44,8 @@ function relinkTiddler(fromTitle,toTitle,options) {
var type = tiddler.fields.type || "";
// Don't touch plugins or JavaScript modules
if(!tiddler.fields["plugin-type"] && type !== "application/javascript") {
var tags = (tiddler.fields.tags || []).slice(0),
list = (tiddler.fields.list || []).slice(0),
var tags = tiddler.fields.tags ? tiddler.fields.tags.slice(0) : undefined,
list = tiddler.fields.list ? tiddler.fields.list.slice(0) : undefined,
isModified = false;
if(!options.dontRenameInTags) {
// Rename tags
+51 -13
View File
@@ -27,6 +27,16 @@ var widget = require("$:/core/modules/widgets/widget.js");
var USER_NAME_TITLE = "$:/status/UserName",
TIMESTAMP_DISABLE_TITLE = "$:/config/TimestampDisable";
/*
Add available indexers to this wiki
*/
exports.addIndexersToWiki = function() {
var self = this;
$tw.utils.each($tw.modules.applyMethods("indexer"),function(Indexer,name) {
self.addIndexer(new Indexer(self),name);
});
};
/*
Get the value of a text reference. Text references can have any of these forms:
<tiddlertitle>
@@ -478,11 +488,18 @@ exports.getOrphanTitles = function() {
Retrieves a list of the tiddler titles that are tagged with a given tag
*/
exports.getTiddlersWithTag = function(tag) {
var self = this;
return this.getGlobalCache("taglist-" + tag,function() {
var tagmap = self.getTagMap();
return self.sortByList(tagmap[tag],tag);
});
// Try to use the indexer
var self = this,
tagIndexer = this.getIndexer("TagIndexer"),
results = tagIndexer && tagIndexer.subIndexers[3].lookup(tag);
if(!results) {
// If not available, perform a manual scan
results = this.getGlobalCache("taglist-" + tag,function() {
var tagmap = self.getTagMap();
return self.sortByList(tagmap[tag],tag);
});
}
return results;
};
/*
@@ -1048,6 +1065,7 @@ Options available:
invert: If true returns tiddlers that do not contain the specified string
caseSensitive: If true forces a case sensitive search
field: If specified, restricts the search to the specified field, or an array of field names
anchored: If true, forces all but regexp searches to be anchored to the start of text
excludeField: If true, the field options are inverted to specify the fields that are not to be searched
The search mode is determined by the first of these boolean flags to be true
literal: searches for literal string
@@ -1062,12 +1080,13 @@ exports.search = function(text,options) {
invert = !!options.invert;
// Convert the search string into a regexp for each term
var terms, searchTermsRegExps,
flags = options.caseSensitive ? "" : "i";
flags = options.caseSensitive ? "" : "i",
anchor = options.anchored ? "^" : "";
if(options.literal) {
if(text.length === 0) {
searchTermsRegExps = null;
} else {
searchTermsRegExps = [new RegExp("(" + $tw.utils.escapeRegExp(text) + ")",flags)];
searchTermsRegExps = [new RegExp("(" + anchor + $tw.utils.escapeRegExp(text) + ")",flags)];
}
} else if(options.whitespace) {
terms = [];
@@ -1076,7 +1095,7 @@ exports.search = function(text,options) {
terms.push($tw.utils.escapeRegExp(term));
}
});
searchTermsRegExps = [new RegExp("(" + terms.join("\\s+") + ")",flags)];
searchTermsRegExps = [new RegExp("(" + anchor + terms.join("\\s+") + ")",flags)];
} else if(options.regexp) {
try {
searchTermsRegExps = [new RegExp("(" + text + ")",flags)];
@@ -1091,7 +1110,7 @@ exports.search = function(text,options) {
} else {
searchTermsRegExps = [];
for(t=0; t<terms.length; t++) {
searchTermsRegExps.push(new RegExp("(" + $tw.utils.escapeRegExp(terms[t]) + ")",flags));
searchTermsRegExps.push(new RegExp("(" + anchor + $tw.utils.escapeRegExp(terms[t]) + ")",flags));
}
}
}
@@ -1369,8 +1388,10 @@ fromPageRect: page coordinates of the origin of the navigation
historyTitle: title of history tiddler (defaults to $:/HistoryList)
*/
exports.addToHistory = function(title,fromPageRect,historyTitle) {
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
story.addToHistory(title,fromPageRect);
if(historyTitle) {
var story = new $tw.Story({wiki: this, historyTitle: historyTitle});
story.addToHistory(title,fromPageRect);
}
};
/*
@@ -1381,8 +1402,25 @@ storyTitle: title of story tiddler (defaults to $:/StoryList)
options: see story.js
*/
exports.addToStory = function(title,fromTitle,storyTitle,options) {
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
story.addToStory(title,fromTitle,options);
if(storyTitle) {
var story = new $tw.Story({wiki: this, storyTitle: storyTitle});
story.addToStory(title,fromTitle,options);
}
};
/*
Generate a title for the draft of a given tiddler
*/
exports.generateDraftTitle = function(title) {
var c = 0,
draftTitle,
username = this.getTiddlerText("$:/status/UserName"),
attribution = username ? " by " + username : "";
do {
draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'" + attribution;
c++;
} while(this.tiddlerExists(draftTitle));
return draftTitle;
};
/*
+120
View File
@@ -0,0 +1,120 @@
title: $:/palettes/Nord
name: Nord
description: An arctic, north-bluish color palette.
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
license: MIT, arcticicestudio, https://github.com/arcticicestudio/nord/blob/develop/LICENSE.md
alert-background: #D08770
alert-border: #D08770
alert-highlight: #B48EAD
alert-muted-foreground: #4C566A
background: #3b4252
blockquote-bar: <<colour muted-foreground>>
button-background: #4C566A
button-foreground: #D8DEE9
button-border: transparent
code-background: #2E3440
code-border: #2E3440
code-foreground: #BF616A
diff-delete-background: #BF616A
diff-delete-foreground: <<colour foreground>>
diff-equal-background:
diff-equal-foreground: <<colour foreground>>
diff-insert-background: #A3BE8C
diff-insert-foreground: <<colour foreground>>
diff-invisible-background:
diff-invisible-foreground: <<colour muted-foreground>>
dirty-indicator: #BF616A
download-background: #A3BE8C
download-foreground: <<colour background>>
dragger-background: <<colour foreground>>
dragger-foreground: <<colour background>>
dropdown-background: <<colour background>>
dropdown-border: <<colour background>>
dropdown-tab-background-selected: #ECEFF4
dropdown-tab-background: #4C566A
dropzone-background: #A3BE8C
external-link-background-hover: inherit
external-link-background-visited: inherit
external-link-background: inherit
external-link-foreground-hover: inherit
external-link-foreground-visited: #5E81AC
external-link-foreground: #8FBCBB
foreground: #d8dee9
message-background: #2E3440
message-border: #2E3440
message-foreground: #547599
modal-backdrop: <<colour foreground>>
modal-background: <<colour background>>
modal-border: #3b4252
modal-footer-background: #3b4252
modal-footer-border: #3b4252
modal-header-border: #3b4252
muted-foreground: #4C566A
notification-background: <<colour primary>>
notification-border: #EBCB8B
page-background: #2e3440
pre-background: #2E3440
pre-border: #2E3440
primary: #5E81AC
select-tag-background: #3b4252
select-tag-foreground: <<colour foreground>>
sidebar-button-foreground: <<colour foreground>>
sidebar-controls-foreground-hover: #4C566A
sidebar-controls-foreground: #3B4252
sidebar-foreground-shadow: transparent
sidebar-foreground: #D8DEE9
sidebar-muted-foreground-hover: #4C566A
sidebar-muted-foreground: #4C566A
sidebar-tab-background-selected: #ECEFF4
sidebar-tab-background: #4C566A
sidebar-tab-border-selected: <<colour tab-border-selected>>
sidebar-tab-border: #4C566A
sidebar-tab-divider: <<colour page-background>>
sidebar-tab-foreground-selected: #4C566A
sidebar-tab-foreground: <<colour tab-foreground>>
sidebar-tiddler-link-foreground-hover: #A3BE8C
sidebar-tiddler-link-foreground: #81A1C1
site-title-foreground: <<colour tiddler-title-foreground>>
static-alert-foreground: #B48EAD
tab-background-selected: #ECEFF4
tab-background: #4C566A
tab-border-selected: #4C566A
tab-border: #4C566A
tab-divider: #4C566A
tab-foreground-selected: #4C566A
tab-foreground: #D8DEE9
table-border: #4C566A
table-footer-background: #2e3440
table-header-background: #2e3440
tag-background: #A3BE8C
tag-foreground: #4C566A
tiddler-background: <<colour background>>
tiddler-border: <<colour background>>
tiddler-controls-foreground-hover:
tiddler-controls-foreground-selected: #EBCB8B
tiddler-controls-foreground: #4C566A
tiddler-editor-background: #2e3440
tiddler-editor-border-image: #2e3440
tiddler-editor-border: #2e3440
tiddler-editor-fields-even: #2e3440
tiddler-editor-fields-odd: #2e3440
tiddler-info-background: #2e3440
tiddler-info-border: #2e3440
tiddler-info-tab-background: #2e3440
tiddler-link-background: <<colour background>>
tiddler-link-foreground: <<colour primary>>
tiddler-subtitle-foreground: #4C566A
tiddler-title-foreground: #81A1C1
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
toolbar-info-button:
toolbar-edit-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-cancel-button:
toolbar-done-button:
untagged-background: #2d3038
very-muted-foreground: #2d3038
+120
View File
@@ -0,0 +1,120 @@
title: $:/palettes/SolarizedLight
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
description: Precision colors for machines and people
license: MIT, Ethan Schoonover, https://github.com/altercation/solarized/blob/master/LICENSE
name: SolarizedLight
alert-background: #eee8d5
alert-border: #073642
alert-highlight: #cb4b16
alert-muted-foreground: #586e75
background: #fdf6e3
blockquote-bar: <<colour muted-foreground>>
button-background: #cb4b16
button-foreground: #fdf6e3
button-border: transparent
code-background: #eee8d5
code-border: #93a1a1
code-foreground: #d33682
diff-delete-background: #BF616A
diff-delete-foreground: <<colour foreground>>
diff-equal-background:
diff-equal-foreground: <<colour foreground>>
diff-insert-background: #859900
diff-insert-foreground: <<colour foreground>>
diff-invisible-background:
diff-invisible-foreground: <<colour muted-foreground>>
dirty-indicator: #D08770
download-background: #859900
download-foreground: <<colour background>>
dragger-background: <<colour foreground>>
dragger-foreground: <<colour background>>
dropdown-background: <<colour background>>
dropdown-border: <<colour background>>
dropdown-tab-background-selected: #fdf6e3
dropdown-tab-background: #93a1a1
dropzone-background: #859900
external-link-background-hover: inherit
external-link-background-visited: inherit
external-link-background: inherit
external-link-foreground-hover: #d33682
external-link-foreground-visited: #b58900
external-link-foreground: #cb4b16
foreground: #839496
message-background: #586e75
message-border: #586e75
message-foreground: #eee8d5
modal-backdrop: <<colour foreground>>
modal-background: <<colour background>>
modal-border: #eee8d5
modal-footer-background: #eee8d5
modal-footer-border: #eee8d5
modal-header-border: #eee8d5
muted-foreground: #93a1a1
notification-background: #EBCB8B
notification-border: #D08770
page-background: #eee8d5
pre-background: #eee8d5
pre-border: #93a1a1
primary: #2aa198
select-tag-background: #eee8d5
select-tag-foreground: <<colour foreground>>
sidebar-button-foreground: #eee8d5
sidebar-controls-foreground-hover: #268bd2
sidebar-controls-foreground: #586e75
sidebar-foreground-shadow: transparent
sidebar-foreground: #839496
sidebar-muted-foreground-hover: #657b83
sidebar-muted-foreground: #93a1a1
sidebar-tab-background-selected: #eee8d5
sidebar-tab-background: #839496
sidebar-tab-border-selected: <<colour tab-border-selected>>
sidebar-tab-border: #657b83
sidebar-tab-divider: <<colour page-background>>
sidebar-tab-foreground-selected: #839496
sidebar-tab-foreground: <<colour tab-foreground>>
sidebar-tiddler-link-foreground-hover: #859900
sidebar-tiddler-link-foreground: #268bd2
site-title-foreground: <<colour tiddler-title-foreground>>
static-alert-foreground: #dc322f
tab-background-selected: #fdf6e3
tab-background: #839496
tab-border-selected: #93a1a1
tab-border: #93a1a1
tab-divider: #fdf6e3
tab-foreground-selected: #839496
tab-foreground: #eee8d5
table-border: #657b83
table-footer-background: #657b83
table-header-background: #93a1a1
tag-background: #6c71c4
tag-foreground: #eee8d5
tiddler-background: <<colour background>>
tiddler-border: <<colour background>>
tiddler-controls-foreground-hover: #b58900
tiddler-controls-foreground-selected: #b58900
tiddler-controls-foreground: #073642
tiddler-editor-background: #eee8d5
tiddler-editor-border-image: #eee8d5
tiddler-editor-border: #eee8d5
tiddler-editor-fields-even: #eee8d5
tiddler-editor-fields-odd: #fdf6e3
tiddler-info-background: #eee8d5
tiddler-info-border: #eee8d5
tiddler-info-tab-background: #586e75
tiddler-link-background: <<colour background>>
tiddler-link-foreground: <<colour primary>>
tiddler-subtitle-foreground: #586e75
tiddler-title-foreground: #073642
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
toolbar-info-button:
toolbar-edit-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-cancel-button:
toolbar-done-button:
untagged-background: #839496
very-muted-foreground: #93a1a1
+111
View File
@@ -0,0 +1,111 @@
title: $:/palettes/SpartanDay
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
description: Cold, spartan day colors
name: Spartan Day
alert-background: <<colour background>>
alert-border: <<colour very-muted-foreground>>
alert-highlight: <<colour very-muted-foreground>>
alert-muted-foreground: <<colour muted-foreground>>
background: #FAFAFA
blockquote-bar: <<colour page-background>>
button-background: transparent
button-foreground: inherit
button-border: <<colour tag-background>>
code-background: #ececec
code-border: #ececec
code-foreground:
dirty-indicator: #c80000
download-background: <<colour primary>>
download-foreground: <<colour background>>
dragger-background: <<colour foreground>>
dragger-foreground: <<colour background>>
dropdown-background: #FFFFFF
dropdown-border: <<colour dropdown-background>>
dropdown-tab-background-selected: <<colour dropdown-background>>
dropdown-tab-background: #F5F5F5
dropzone-background: <<colour tag-background>>
external-link-background-hover: transparent
external-link-background-visited: transparent
external-link-background: transparent
external-link-foreground-hover:
external-link-foreground-visited:
external-link-foreground:
foreground: rgba(0, 0, 0, 0.87)
message-background: <<colour background>>
message-border: <<colour very-muted-foreground>>
message-foreground: rgba(0, 0, 0, 0.54)
modal-backdrop: <<colour foreground>>
modal-background: <<colour background>>
modal-border: <<colour very-muted-foreground>>
modal-footer-background: <<colour background>>
modal-footer-border: <<colour very-muted-foreground>>
modal-header-border: <<colour very-muted-foreground>>
muted-foreground: rgba(0, 0, 0, 0.54)
notification-background: <<colour dropdown-background>>
notification-border: <<colour dropdown-background>>
page-background: #f4f4f4
pre-background: #ececec
pre-border: #ececec
primary: #3949ab
select-tag-background: <<colour background>>
select-tag-foreground: <<colour foreground>>
sidebar-button-foreground: <<colour foreground>>
sidebar-controls-foreground-hover: #aeaeae
sidebar-controls-foreground: #c6c6c6
sidebar-foreground-shadow: transparent
sidebar-foreground: rgba(0, 0, 0, 0.54)
sidebar-muted-foreground-hover: rgba(0, 0, 0, 0.54)
sidebar-muted-foreground: rgba(0, 0, 0, 0.38)
sidebar-tab-background-selected: <<colour page-background>>
sidebar-tab-background: transparent
sidebar-tab-border-selected: <<colour table-border>>
sidebar-tab-border: transparent
sidebar-tab-divider: <<colour table-border>>
sidebar-tab-foreground-selected: rgba(0, 0, 0, 0.87)
sidebar-tab-foreground: rgba(0, 0, 0, 0.54)
sidebar-tiddler-link-foreground-hover: rgba(0, 0, 0, 0.87)
sidebar-tiddler-link-foreground: rgba(0, 0, 0, 0.54)
site-title-foreground: rgba(0, 0, 0, 0.87)
static-alert-foreground: #aaaaaa
tab-background-selected: <<colour background>>
tab-background: transparent
tab-border-selected: <<colour table-border>>
tab-border: transparent
tab-divider: <<colour table-border>>
tab-foreground-selected: rgba(0, 0, 0, 0.87)
tab-foreground: rgba(0, 0, 0, 0.54)
table-border: #d8d8d8
table-footer-background: <<colour tiddler-editor-fields-odd>>
table-header-background: <<colour tiddler-editor-fields-even>>
tag-background: #ec6
tag-foreground: <<colour button-foreground>>
tiddler-background: <<colour background>>
tiddler-border: #f9f9f9
tiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>
tiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>
tiddler-controls-foreground: <<colour sidebar-controls-foreground>>
tiddler-editor-background: transparent
tiddler-editor-border-image:
tiddler-editor-border: #e8e7e7
tiddler-editor-fields-even: rgba(0, 0, 0, 0.1)
tiddler-editor-fields-odd: rgba(0, 0, 0, 0.04)
tiddler-info-background: #F5F5F5
tiddler-info-border: #F5F5F5
tiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>
tiddler-link-background: <<colour background>>
tiddler-link-foreground: <<colour primary>>
tiddler-subtitle-foreground: <<colour muted-foreground>>
tiddler-title-foreground: #000000
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
toolbar-info-button:
toolbar-edit-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-cancel-button:
toolbar-done-button:
untagged-background: <<colour very-muted-foreground>>
very-muted-foreground: rgba(0, 0, 0, 0.12)
+111
View File
@@ -0,0 +1,111 @@
title: $:/palettes/SpartanNight
tags: $:/tags/Palette
type: application/x-tiddler-dictionary
description: Dark spartan colors
name: Spartan Night
alert-background: <<colour background>>
alert-border: <<colour very-muted-foreground>>
alert-highlight: <<colour very-muted-foreground>>
alert-muted-foreground: <<colour muted-foreground>>
background: #303030
blockquote-bar: <<colour page-background>>
button-background: transparent
button-foreground: inherit
button-border: <<colour tag-background>>
code-background: <<colour pre-background>>
code-border: <<colour pre-border>>
code-foreground: rgba(255, 255, 255, 0.54)
dirty-indicator: #c80000
download-background: <<colour primary>>
download-foreground: <<colour foreground>>
dragger-background: <<colour foreground>>
dragger-foreground: <<colour background>>
dropdown-background: #424242
dropdown-border: <<colour dropdown-background>>
dropdown-tab-background-selected: <<colour dropdown-background>>
dropdown-tab-background: #050505
dropzone-background: <<colour tag-background>>
external-link-background-hover: transparent
external-link-background-visited: transparent
external-link-background: transparent
external-link-foreground-hover:
external-link-foreground-visited: #7c318c
external-link-foreground: #9e3eb3
foreground: rgba(255, 255, 255, 0.7)
message-background: <<colour background>>
message-border: <<colour very-muted-foreground>>
message-foreground: rgba(255, 255, 255, 0.54)
modal-backdrop: <<colour page-background>>
modal-background: <<colour background>>
modal-border: <<colour very-muted-foreground>>
modal-footer-background: <<colour background>>
modal-footer-border: <<colour background>>
modal-header-border: <<colour very-muted-foreground>>
muted-foreground: rgba(255, 255, 255, 0.54)
notification-background: <<colour dropdown-background>>
notification-border: <<colour dropdown-background>>
page-background: #212121
pre-background: #2a2a2a
pre-border: transparent
primary: #5656f3
select-tag-background: <<colour background>>
select-tag-foreground: <<colour foreground>>
sidebar-button-foreground: <<colour foreground>>
sidebar-controls-foreground-hover: #494949
sidebar-controls-foreground: #5d5d5d
sidebar-foreground-shadow: transparent
sidebar-foreground: rgba(255, 255, 255, 0.54)
sidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54)
sidebar-muted-foreground: rgba(255, 255, 255, 0.38)
sidebar-tab-background-selected: <<colour page-background>>
sidebar-tab-background: transparent
sidebar-tab-border-selected: <<colour table-border>>
sidebar-tab-border: transparent
sidebar-tab-divider: <<colour table-border>>
sidebar-tab-foreground-selected: rgba(255, 255, 255, 0.87)
sidebar-tab-foreground: rgba(255, 255, 255, 0.54)
sidebar-tiddler-link-foreground-hover: rgba(255, 255, 255, 0.7)
sidebar-tiddler-link-foreground: rgba(255, 255, 255, 0.54)
site-title-foreground: rgba(255, 255, 255, 0.7)
static-alert-foreground: #aaaaaa
tab-background-selected: <<colour background>>
tab-background: transparent
tab-border-selected: <<colour table-border>>
tab-border: transparent
tab-divider: <<colour table-border>>
tab-foreground-selected: rgba(255, 255, 255, 0.87)
tab-foreground: rgba(255, 255, 255, 0.54)
table-border: #3a3a3a
table-footer-background: <<colour tiddler-editor-fields-odd>>
table-header-background: <<colour tiddler-editor-fields-even>>
tag-background: #ec6
tag-foreground: <<colour button-foreground>>
tiddler-background: <<colour background>>
tiddler-border: rgb(55,55,55)
tiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>>
tiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>>
tiddler-controls-foreground: <<colour sidebar-controls-foreground>>
tiddler-editor-background: transparent
tiddler-editor-border-image:
tiddler-editor-border: rgba(255, 255, 255, 0.08)
tiddler-editor-fields-even: rgba(255, 255, 255, 0.1)
tiddler-editor-fields-odd: rgba(255, 255, 255, 0.04)
tiddler-info-background: #454545
tiddler-info-border: #454545
tiddler-info-tab-background: <<colour tiddler-editor-fields-odd>>
tiddler-link-background: <<colour background>>
tiddler-link-foreground: <<colour primary>>
tiddler-subtitle-foreground: <<colour muted-foreground>>
tiddler-title-foreground: #FFFFFF
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
toolbar-info-button:
toolbar-edit-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-cancel-button:
toolbar-done-button:
untagged-background: <<colour very-muted-foreground>>
very-muted-foreground: rgba(255, 255, 255, 0.12)
+120
View File
@@ -0,0 +1,120 @@
title: $:/palettes/Twilight
tags: $:/tags/Palette
author: Thomas Elmiger
type: application/x-tiddler-dictionary
name: Twilight
description: Delightful, soft darkness.
alert-background: rgb(255, 255, 102)
alert-border: rgb(232, 232, 125)
alert-highlight: rgb(255, 51, 51)
alert-muted-foreground: rgb(224, 82, 82)
background: rgb(38, 38, 38)
blockquote-bar: rgba(240, 196, 117, 0.7)
button-background: rgb(63, 63, 63)
button-border: rgb(127, 127, 127)
button-foreground: rgb(179, 179, 179)
code-background: rgba(0,0,0,0.03)
code-border: rgba(0,0,0,0.08)
code-foreground: rgb(255, 94, 94)
diff-delete-background: #ffc9c9
diff-delete-foreground: <<colour foreground>>
diff-equal-background:
diff-equal-foreground: <<colour foreground>>
diff-insert-background: #aaefad
diff-insert-foreground: <<colour foreground>>
diff-invisible-background:
diff-invisible-foreground: <<colour muted-foreground>>
dirty-indicator: rgb(255, 94, 94)
download-background: #19a974
download-foreground: rgb(38, 38, 38)
dragger-background: rgb(179, 179, 179)
dragger-foreground: rgb(38, 38, 38)
dropdown-background: rgb(38, 38, 38)
dropdown-border: rgb(255, 255, 255)
dropdown-tab-background: rgba(0,0,0,.1)
dropdown-tab-background-selected: rgba(255,255,255,1)
dropzone-background: #9eebcf
external-link-background: inherit
external-link-background-hover: inherit
external-link-background-visited: inherit
external-link-foreground: rgb(179, 179, 255)
external-link-foreground-hover: inherit
external-link-foreground-visited: rgb(153, 153, 255)
foreground: rgb(179, 179, 179)
message-background: <<colour tag-foreground>>
message-border: #96ccff
message-foreground: <<colour tag-background>>
modal-backdrop: rgb(179, 179, 179)
modal-background: rgb(38, 38, 38)
modal-border: rgba(0,0,0,.5)
modal-footer-background: #f4f4f4
modal-footer-border: rgba(0,0,0,.1)
modal-header-border: rgba(0,0,0,.2)
muted-foreground: rgb(255, 255, 255)
notification-background: <<colour tag-foreground>>
notification-border: <<colour tag-background>>
page-background: rgb(26, 26, 26)
pre-background: rgb(25, 25, 25)
pre-border: rgba(0,0,0,.2)
primary: rgb(255, 201, 102)
select-tag-background:
select-tag-foreground:
sidebar-button-foreground: rgb(179, 179, 179)
sidebar-controls-foreground: rgb(153, 153, 153)
sidebar-controls-foreground-hover: <<colour tiddler-controls-foreground-hover>>
sidebar-foreground: rgb(141, 141, 141)
sidebar-foreground-shadow: transparent
sidebar-muted-foreground: rgba(0, 0, 0, 0.5)
sidebar-muted-foreground-hover: rgb(141, 141, 141)
sidebar-tab-background: rgba(141, 141, 141, 0.2)
sidebar-tab-background-selected: rgb(26, 26, 26)
sidebar-tab-border: rgb(127, 127, 127)
sidebar-tab-border-selected: rgb(127, 127, 127)
sidebar-tab-divider: rgb(127, 127, 127)
sidebar-tab-foreground: rgb(179, 179, 179)
sidebar-tab-foreground-selected: rgb(179, 179, 179)
sidebar-tiddler-link-foreground: rgb(179, 179, 179)
sidebar-tiddler-link-foreground-hover: rgb(115, 115, 115)
site-title-foreground: rgb(255, 201, 102)
static-alert-foreground: rgba(0,0,0,.3)
tab-background: rgba(0,0,0,0.125)
tab-background-selected: rgb(38, 38, 38)
tab-border: rgb(255, 201, 102)
tab-border-selected: rgb(255, 201, 102)
tab-divider: rgb(255, 201, 102)
tab-foreground: rgb(179, 179, 179)
tab-foreground-selected: rgb(179, 179, 179)
table-border: rgba(255,255,255,.3)
table-footer-background: rgba(0,0,0,.4)
table-header-background: rgba(0,0,0,.1)
tag-background: rgb(255, 201, 102)
tag-foreground: rgb(25, 25, 25)
tiddler-background: rgb(38, 38, 38)
tiddler-border: rgba(240, 196, 117, 0.7)
tiddler-controls-foreground: rgb(128, 128, 128)
tiddler-controls-foreground-hover: rgba(255, 255, 255, 0.8)
tiddler-controls-foreground-selected: rgba(255, 255, 255, 0.9)
tiddler-editor-background: rgb(33, 33, 33)
tiddler-editor-border: rgb(63, 63, 63)
tiddler-editor-border-image: rgb(25, 25, 25)
tiddler-editor-fields-even: rgb(33, 33, 33)
tiddler-editor-fields-odd: rgb(28, 28, 28)
tiddler-info-background: rgb(43, 43, 43)
tiddler-info-border: rgb(25, 25, 25)
tiddler-info-tab-background: rgb(43, 43, 43)
tiddler-link-background: rgb(38, 38, 38)
tiddler-link-foreground: rgb(204, 204, 255)
tiddler-subtitle-foreground: rgb(255, 255, 255)
tiddler-title-foreground: rgb(255, 192, 76)
toolbar-cancel-button:
toolbar-close-button:
toolbar-delete-button:
toolbar-done-button:
toolbar-edit-button:
toolbar-info-button:
toolbar-new-button:
toolbar-options-button:
toolbar-save-button:
untagged-background: rgb(255, 255, 255)
very-muted-foreground: rgba(240, 196, 117, 0.7)

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