mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-25 12:23:42 +00:00
Compare commits
408 Commits
v5.0.0-alp
...
v5.0.7-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f6ee1d2a8 | ||
|
|
183e9544b4 | ||
|
|
dfc57ffa49 | ||
|
|
3f9561dd95 | ||
|
|
37ca86ff3d | ||
|
|
cf26986061 | ||
|
|
54822e25d4 | ||
|
|
4a9108154d | ||
|
|
8a88253b4e | ||
|
|
7891824883 | ||
|
|
fca5681a1a | ||
|
|
5c9a5f5cba | ||
|
|
69d342d46a | ||
|
|
66254b436c | ||
|
|
d42981f201 | ||
|
|
04dbf99e54 | ||
|
|
762940adbc | ||
|
|
f58d4fb531 | ||
|
|
45c45e098f | ||
|
|
b5629ccc82 | ||
|
|
bd067c6b1e | ||
|
|
1d10ccb368 | ||
|
|
9297b27b89 | ||
|
|
0b3efe179e | ||
|
|
e6843aabff | ||
|
|
02d3861d7d | ||
|
|
592ef257a2 | ||
|
|
6ba9bf9a95 | ||
|
|
18fe0c0f75 | ||
|
|
c49681ecf3 | ||
|
|
6255b97b14 | ||
|
|
6cb44ac0cc | ||
|
|
b1b9c7d6cd | ||
|
|
951147d502 | ||
|
|
9539664e46 | ||
|
|
f9b5d75446 | ||
|
|
70a7321edd | ||
|
|
9522050aa7 | ||
|
|
8d37219545 | ||
|
|
a76da88380 | ||
|
|
42262a637c | ||
|
|
e6a7a0db1e | ||
|
|
edc71cb920 | ||
|
|
bd48ecfcb1 | ||
|
|
f4b27b33de | ||
|
|
644d88a6c5 | ||
|
|
43eb81173d | ||
|
|
a8eff78b62 | ||
|
|
f90db97625 | ||
|
|
e339b6dffe | ||
|
|
64304f9b7f | ||
|
|
867dfabff8 | ||
|
|
b627bba277 | ||
|
|
b9b1b001da | ||
|
|
e9ae8d2015 | ||
|
|
2fc6451bf7 | ||
|
|
f31369035b | ||
|
|
1e54b1bcc9 | ||
|
|
d3c421985c | ||
|
|
1c283c5586 | ||
|
|
4f5a923ca0 | ||
|
|
95cb99adb9 | ||
|
|
d5df78d979 | ||
|
|
ed5cf8b044 | ||
|
|
98edbec46d | ||
|
|
299e9d15fb | ||
|
|
2f4932fefc | ||
|
|
5f1d49f2e0 | ||
|
|
6ea9dc997f | ||
|
|
c9d06ad18a | ||
|
|
3414f1ca8e | ||
|
|
60926198b1 | ||
|
|
2c790d982f | ||
|
|
839361d54f | ||
|
|
14ca91a949 | ||
|
|
81de74342d | ||
|
|
0338c36610 | ||
|
|
c7fb0bd349 | ||
|
|
d7d5165847 | ||
|
|
aefc7b7ce2 | ||
|
|
1657111cb7 | ||
|
|
08a8689117 | ||
|
|
b1b38dc143 | ||
|
|
22f48198bd | ||
|
|
4072c4461d | ||
|
|
43fb16f232 | ||
|
|
809c441ab3 | ||
|
|
9985efa406 | ||
|
|
84e149e36c | ||
|
|
25423d2d07 | ||
|
|
12770ca3e6 | ||
|
|
a5d75db8d2 | ||
|
|
9444ef095f | ||
|
|
b04141fefd | ||
|
|
c74bf6a655 | ||
|
|
19080f9958 | ||
|
|
b5d2b79a37 | ||
|
|
17b542980f | ||
|
|
8f4e1587a2 | ||
|
|
4b000fac72 | ||
|
|
426f2978cf | ||
|
|
bad2e36e45 | ||
|
|
a4f895dc4d | ||
|
|
e254529763 | ||
|
|
5dff212e5a | ||
|
|
b7a1db1e9f | ||
|
|
6964120fce | ||
|
|
a704498155 | ||
|
|
83811bc2a9 | ||
|
|
bd40977c85 | ||
|
|
e87097c22e | ||
|
|
e74cb05540 | ||
|
|
b326315b0e | ||
|
|
a3384d101e | ||
|
|
8ef520ef37 | ||
|
|
b64b7982af | ||
|
|
c5035fc0b0 | ||
|
|
2740f8c1f0 | ||
|
|
209bc78268 | ||
|
|
ffcc215e8f | ||
|
|
0fb13e649b | ||
|
|
b42eefe1e8 | ||
|
|
82a48cf85c | ||
|
|
9fee9b1043 | ||
|
|
d57010d2fb | ||
|
|
f2409d4245 | ||
|
|
4181de5b74 | ||
|
|
954901d788 | ||
|
|
4688190c96 | ||
|
|
a1d2e70307 | ||
|
|
e0f428b9b2 | ||
|
|
504f353844 | ||
|
|
7857464ab5 | ||
|
|
103f4f6637 | ||
|
|
b06e09a4d3 | ||
|
|
9d72570092 | ||
|
|
1638824adc | ||
|
|
79bed656bb | ||
|
|
6fcfa2738a | ||
|
|
47ebed87f9 | ||
|
|
3c35c9ecf8 | ||
|
|
027421f5e6 | ||
|
|
1a74e2538c | ||
|
|
8fc5c1d4a0 | ||
|
|
1374bd9d78 | ||
|
|
307b5c7d6b | ||
|
|
5dea8ca758 | ||
|
|
3677fdd3b0 | ||
|
|
5758fcb69b | ||
|
|
385099c4f7 | ||
|
|
2343bb3e5b | ||
|
|
b132e1023d | ||
|
|
2d99f4dc15 | ||
|
|
c9b319c41c | ||
|
|
b652238650 | ||
|
|
d0cd72ed85 | ||
|
|
4289367b7f | ||
|
|
b76ca5dc3b | ||
|
|
71b5c561f2 | ||
|
|
6a02535d08 | ||
|
|
87fbd988f1 | ||
|
|
3d79eb87d1 | ||
|
|
089a838611 | ||
|
|
e48e7e9443 | ||
|
|
917865c393 | ||
|
|
ec14a0a16d | ||
|
|
b9e80a270b | ||
|
|
44568dc6ef | ||
|
|
d043bdd289 | ||
|
|
ce8cc7607f | ||
|
|
6d6e8afb9c | ||
|
|
bb0be9e02f | ||
|
|
5dd33904e7 | ||
|
|
2ee5093944 | ||
|
|
87a553d75d | ||
|
|
ec7dff291d | ||
|
|
de2e5adf15 | ||
|
|
b3ad61ce20 | ||
|
|
5eb57365b6 | ||
|
|
c49bc2b0a6 | ||
|
|
3494dd019d | ||
|
|
784e6d17f0 | ||
|
|
9efd45dda9 | ||
|
|
eb7b82696b | ||
|
|
3b114371d0 | ||
|
|
14868d8228 | ||
|
|
3cc8138133 | ||
|
|
b6f2f1e1aa | ||
|
|
424147234e | ||
|
|
8e080eac0a | ||
|
|
38142d2b19 | ||
|
|
bd7db62da0 | ||
|
|
4cdfbd6b36 | ||
|
|
ef59a3743f | ||
|
|
cee1bc0863 | ||
|
|
ce8c79ecfa | ||
|
|
ac81d9d43f | ||
|
|
d69614259f | ||
|
|
0e88417e62 | ||
|
|
46892371cb | ||
|
|
f9de55ad5f | ||
|
|
81106e500d | ||
|
|
cfad04a5d0 | ||
|
|
1aa5dedfaf | ||
|
|
98fdd3e184 | ||
|
|
73c5ecdaa7 | ||
|
|
eef32e70e3 | ||
|
|
ad6bf4f9c5 | ||
|
|
7db31dc138 | ||
|
|
7b7e799a70 | ||
|
|
3aab737bea | ||
|
|
12b4cc5d3e | ||
|
|
10c25c1692 | ||
|
|
c35742f916 | ||
|
|
15a41d7e57 | ||
|
|
4e37fa7e47 | ||
|
|
1c17cfb0ff | ||
|
|
912c26f848 | ||
|
|
a5de1cf7fb | ||
|
|
84e0dc9d1a | ||
|
|
39743b4758 | ||
|
|
6091b41960 | ||
|
|
2d1d53893a | ||
|
|
861e350444 | ||
|
|
9a15cb0516 | ||
|
|
74fd683a22 | ||
|
|
8cc10d87d4 | ||
|
|
ce13548884 | ||
|
|
ffcc5a09f2 | ||
|
|
7f5a8fc937 | ||
|
|
c740792105 | ||
|
|
bd80bf4acc | ||
|
|
e66fb948c1 | ||
|
|
79046c52b4 | ||
|
|
062c4e5400 | ||
|
|
8538d69dc1 | ||
|
|
274c52005d | ||
|
|
99dd029816 | ||
|
|
1c529ddcd4 | ||
|
|
1491c261f5 | ||
|
|
3bcaab513d | ||
|
|
04077549ca | ||
|
|
6c1489fc2f | ||
|
|
1336058336 | ||
|
|
b659c65959 | ||
|
|
e8f16c1c97 | ||
|
|
6b51a51609 | ||
|
|
a4d063e884 | ||
|
|
42ba6852d1 | ||
|
|
638c8b2070 | ||
|
|
cc39686693 | ||
|
|
2b72e48a3a | ||
|
|
0ec2224757 | ||
|
|
218b9c967e | ||
|
|
a4e4b6797a | ||
|
|
a4e3f66809 | ||
|
|
07dd524016 | ||
|
|
f3b2788ed1 | ||
|
|
a389f9bc8c | ||
|
|
1144504bb3 | ||
|
|
72f07947ea | ||
|
|
e8549cba4b | ||
|
|
a5aa2c08b2 | ||
|
|
14b98f5966 | ||
|
|
7ec516a746 | ||
|
|
886b069dce | ||
|
|
b50eb8da30 | ||
|
|
4ece301a97 | ||
|
|
810167bc7b | ||
|
|
1b2a5fe130 | ||
|
|
88d483a2c8 | ||
|
|
db85bfe513 | ||
|
|
066a4d9fbc | ||
|
|
3e2f475324 | ||
|
|
a5f33d875b | ||
|
|
6d09db5608 | ||
|
|
23b2f74e94 | ||
|
|
37a46adac8 | ||
|
|
65e3780cc1 | ||
|
|
7d33dd71a2 | ||
|
|
d03728ea71 | ||
|
|
9396d52b42 | ||
|
|
7dc7559b90 | ||
|
|
5ac5b2c76d | ||
|
|
d4d8cdf9a4 | ||
|
|
9e5e08a7d3 | ||
|
|
41c592b758 | ||
|
|
84ad161eab | ||
|
|
4ab431bb93 | ||
|
|
f6bea8f58b | ||
|
|
b8c9422161 | ||
|
|
d7ebd461f2 | ||
|
|
57adbe5bf7 | ||
|
|
34e6d79ef6 | ||
|
|
713d6945c6 | ||
|
|
ef9175e7bc | ||
|
|
6a8feb216a | ||
|
|
b1e7ba29f1 | ||
|
|
79c8935aef | ||
|
|
8496337d30 | ||
|
|
2126ce1d17 | ||
|
|
3f06384516 | ||
|
|
053e09af6e | ||
|
|
0984e9322f | ||
|
|
c190b0f1ea | ||
|
|
80e0714c0d | ||
|
|
819843e4b0 | ||
|
|
6386e60896 | ||
|
|
7c9b920e26 | ||
|
|
ae4a2b58ed | ||
|
|
c73a7af95b | ||
|
|
1420aa2f58 | ||
|
|
0814f3623d | ||
|
|
382d7e4449 | ||
|
|
e2cd611e45 | ||
|
|
bb03bb942f | ||
|
|
fd996bad20 | ||
|
|
3f3cac12ba | ||
|
|
761b66028d | ||
|
|
7e151a98da | ||
|
|
e537457d4b | ||
|
|
e686d62400 | ||
|
|
ae6d1b1685 | ||
|
|
49b3165fbd | ||
|
|
6a21965cee | ||
|
|
b9faadbbc9 | ||
|
|
c610161455 | ||
|
|
6dbd178378 | ||
|
|
77bca22d42 | ||
|
|
9f058925f7 | ||
|
|
1b75242345 | ||
|
|
6298c7aa43 | ||
|
|
853cca906c | ||
|
|
cffe9375b2 | ||
|
|
b8897f86fb | ||
|
|
409311b61e | ||
|
|
d11cda4854 | ||
|
|
6a71b399b0 | ||
|
|
2e188a48f4 | ||
|
|
b4733414e5 | ||
|
|
67072371a0 | ||
|
|
a9c209c62e | ||
|
|
bc84df1707 | ||
|
|
062822d45c | ||
|
|
2e0e8a879f | ||
|
|
2ffcbb76eb | ||
|
|
50e1727ef7 | ||
|
|
7a99fb1250 | ||
|
|
e6e47ca83d | ||
|
|
489b40314b | ||
|
|
14cf9ad24a | ||
|
|
428e27d4bf | ||
|
|
0edf46dee1 | ||
|
|
c38cd500f6 | ||
|
|
3da825c6e1 | ||
|
|
559f9da9b4 | ||
|
|
8f6e3c641d | ||
|
|
aae8587660 | ||
|
|
5bb7ee2f88 | ||
|
|
0a93edb1b6 | ||
|
|
b0ff8bee6a | ||
|
|
48f8046cf5 | ||
|
|
d4e6516a61 | ||
|
|
1fddcf075f | ||
|
|
d64c37c3b7 | ||
|
|
ffcf2bfaac | ||
|
|
4d4a0e01b4 | ||
|
|
b37a139aa7 | ||
|
|
17277cf8fd | ||
|
|
374743883d | ||
|
|
d739b6939a | ||
|
|
49ade66540 | ||
|
|
09e14dd8ad | ||
|
|
c30392c0c5 | ||
|
|
fa8cc1c512 | ||
|
|
21f795b542 | ||
|
|
1363d24e86 | ||
|
|
4cffa58df3 | ||
|
|
7d0b930335 | ||
|
|
f3954d374d | ||
|
|
16170ce504 | ||
|
|
9dcbdb5297 | ||
|
|
ecdfce1985 | ||
|
|
88e0bd3251 | ||
|
|
5ccd4988aa | ||
|
|
1e99f6cb67 | ||
|
|
41fc06ab4d | ||
|
|
b149ab47f4 | ||
|
|
1b99dbb677 | ||
|
|
c4814cec91 | ||
|
|
698efb66bb | ||
|
|
7a4abba9fd | ||
|
|
026a27c1ab | ||
|
|
34ae1387a5 | ||
|
|
62b9fb336b | ||
|
|
8ed364ed72 | ||
|
|
b1aadc7e94 | ||
|
|
eb41ca578d | ||
|
|
2ec58f7fa2 | ||
|
|
6be7e2c30e | ||
|
|
7ebb8702b2 | ||
|
|
eac07fb6c3 | ||
|
|
3a07cd4c55 | ||
|
|
a12310f225 | ||
|
|
593503fe09 | ||
|
|
7f4dffca77 | ||
|
|
f9f9c96ca1 | ||
|
|
5e743262d4 |
17
bld.cmd
17
bld.cmd
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
|
||||
rem build TiddlyWiki5 for five.tiddlywiki.com
|
||||
rem build TiddlyWiki5 for tiddlywiki.com
|
||||
|
||||
rem Set up the build output directory
|
||||
|
||||
@@ -35,10 +35,15 @@ node .\tiddlywiki.js ^
|
||||
.\editions\tw5.com ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\index.html text/plain ^
|
||||
--savetiddler $:/favicon.ico %TW5_BUILD_OUTPUT%\favicon.ico ^
|
||||
--rendertiddler ReadMe .\readme.md text/html ^
|
||||
--rendertiddler ContributingTemplate .\contributing.md text/html ^
|
||||
--rendertiddler $:/core/copyright.txt .\licenses\copyright.md text/plain ^
|
||||
--rendertiddler $:/editions/tw5.com/download-empty %TW5_BUILD_OUTPUT%\empty.html text/plain ^
|
||||
--rendertiddler $:/editions/tw5.com/download-empty %TW5_BUILD_OUTPUT%\empty.hta text/plain ^
|
||||
--savetiddler $:/green_favicon.ico %TW5_BUILD_OUTPUT%/static/favicon.ico ^
|
||||
--rendertiddler $:/core/templates/static.template.html %TW5_BUILD_OUTPUT%\static.html text/plain ^
|
||||
--rendertiddler $:/core/templates/alltiddlers.template.html %TW5_BUILD_OUTPUT%\alltiddlers.html text/plain ^
|
||||
--rendertiddler $:/core/templates/static.template.css %TW5_BUILD_OUTPUT%\static\static.css text/plain ^
|
||||
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html %TW5_BUILD_OUTPUT%\static text/plain ^
|
||||
|| exit 1
|
||||
@@ -85,9 +90,17 @@ node .\tiddlywiki.js ^
|
||||
|| exit 1
|
||||
|
||||
|
||||
rem highlightdemo.html: wiki to demo highlight plugin
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\highlightdemo ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\highlightdemo.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
rem Make the CNAME file that GitHub Pages requires
|
||||
|
||||
echo five.tiddlywiki.com > %TW5_BUILD_OUTPUT%\CNAME
|
||||
echo tiddlywiki.com > %TW5_BUILD_OUTPUT%\CNAME
|
||||
|
||||
rem Run the test edition to run the Node.js tests and to generate test.html for tests in the browser
|
||||
|
||||
|
||||
17
bld.sh
17
bld.sh
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# build TiddlyWiki5 for five.tiddlywiki.com
|
||||
# build TiddlyWiki5 for tiddlywiki.com
|
||||
|
||||
# Set up the build output directory
|
||||
|
||||
@@ -17,7 +17,7 @@ echo "Using TW5_BUILD_OUTPUT as [$TW5_BUILD_OUTPUT]"
|
||||
|
||||
# Make the CNAME file that GitHub Pages requires
|
||||
|
||||
echo "five.tiddlywiki.com" > $TW5_BUILD_OUTPUT/CNAME
|
||||
echo "tiddlywiki.com" > $TW5_BUILD_OUTPUT/CNAME
|
||||
|
||||
# Create the `static` directories if necessary
|
||||
|
||||
@@ -36,10 +36,15 @@ node ./tiddlywiki.js \
|
||||
./editions/tw5.com \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/index.html text/plain \
|
||||
--savetiddler $:/favicon.ico $TW5_BUILD_OUTPUT/favicon.ico \
|
||||
--rendertiddler ReadMe ./readme.md text/html \
|
||||
--rendertiddler ContributingTemplate ./contributing.md text/html \
|
||||
--rendertiddler $:/core/copyright.txt ./licenses/copyright.md text/plain \
|
||||
--rendertiddler $:/editions/tw5.com/download-empty $TW5_BUILD_OUTPUT/empty.html text/plain \
|
||||
--rendertiddler $:/editions/tw5.com/download-empty $TW5_BUILD_OUTPUT/empty.hta text/plain \
|
||||
--savetiddler $:/green_favicon.ico $TW5_BUILD_OUTPUT/static/favicon.ico \
|
||||
--rendertiddler $:/core/templates/static.template.html $TW5_BUILD_OUTPUT/static.html text/plain \
|
||||
--rendertiddler $:/core/templates/alltiddlers.template.html $TW5_BUILD_OUTPUT/alltiddlers.html text/plain \
|
||||
--rendertiddler $:/core/templates/static.template.css $TW5_BUILD_OUTPUT/static/static.css text/plain \
|
||||
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html $TW5_BUILD_OUTPUT/static text/plain \
|
||||
|| exit 1
|
||||
@@ -85,6 +90,14 @@ node ./tiddlywiki.js \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/markdowndemo.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# highlightdemo.html: wiki to demo highlight plugin
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/highlightdemo \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/highlightdemo.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Run the test edition to run the Node.js tests and to generate test.html for tests in the browser
|
||||
|
||||
./test.sh
|
||||
|
||||
@@ -14,10 +14,10 @@ Error message and password prompt
|
||||
z-index: 20000;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
width: 480px;
|
||||
width: 200px;
|
||||
top: 4em;
|
||||
left: 50%;
|
||||
margin-left: -264px; /* - width/2 - paddingHorz/2 - border */
|
||||
margin-left: -144px; /* - width/2 - paddingHorz/2 - border */
|
||||
padding: 16px 16px 16px 16px;
|
||||
-webkit-border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
@@ -29,6 +29,8 @@ Error message and password prompt
|
||||
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
|
||||
background-color: rgb(255, 75, 75);
|
||||
border: 8px solid rgb(255, 0, 0);
|
||||
width: 480px;
|
||||
margin-left: -244px; /* - width/2 - paddingHorz/2 - border */
|
||||
}
|
||||
|
||||
.tw-error-form div {
|
||||
@@ -54,4 +56,9 @@ Error message and password prompt
|
||||
.tw-password-wrapper h1 {
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.tw-password-wrapper input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
211
boot/boot.js
211
boot/boot.js
@@ -38,7 +38,7 @@ $tw.boot = $tw.boot || {};
|
||||
/////////////////////////// Standard node.js libraries
|
||||
|
||||
var fs, path, vm;
|
||||
if(!$tw.browser) {
|
||||
if($tw.node) {
|
||||
fs = require("fs");
|
||||
path = require("path");
|
||||
vm = require("vm");
|
||||
@@ -46,15 +46,6 @@ if(!$tw.browser) {
|
||||
|
||||
/////////////////////////// Utility functions
|
||||
|
||||
/*
|
||||
Log a message
|
||||
*/
|
||||
$tw.utils.log = function(/* args */) {
|
||||
if(console !== undefined && console.log !== undefined) {
|
||||
return Function.apply.call(console.log, console, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Check if an object has a property
|
||||
*/
|
||||
@@ -207,10 +198,10 @@ $tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
|
||||
};
|
||||
|
||||
/*
|
||||
Convert "&" to &, "<" to <, ">" to > and """ to "
|
||||
Convert "&" to &, " " to nbsp, "<" to <, ">" to > and """ to "
|
||||
*/
|
||||
$tw.utils.htmlDecode = function(s) {
|
||||
return s.toString().replace(/</mg,"<").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||||
return s.toString().replace(/</mg,"<").replace(/ /mg,"\x40").replace(/>/mg,">").replace(/"/mg,"\"").replace(/&/mg,"&");
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -246,7 +237,7 @@ $tw.utils.parseDate = function(value) {
|
||||
parseInt(value.substr(10,2)||"00",10),
|
||||
parseInt(value.substr(12,2)||"00",10),
|
||||
parseInt(value.substr(14,3)||"000",10)));
|
||||
} else if ($tw.utils.isDate(value)) {
|
||||
} else if($tw.utils.isDate(value)) {
|
||||
return value;
|
||||
} else {
|
||||
return null;
|
||||
@@ -269,7 +260,7 @@ $tw.utils.stringifyList = function(value) {
|
||||
// Parse a string array from a bracketted list. For example "OneTiddler [[Another Tiddler]] LastOne"
|
||||
$tw.utils.parseStringArray = function(value) {
|
||||
if(typeof value === "string") {
|
||||
var memberRegExp = /(?:\[\[([^\]]+)\]\])|([^\s]+)/mg,
|
||||
var memberRegExp = /(?:^|\s)(?:\[\[(.*?)\]\])(?=\s|$)|(\S+)/mg,
|
||||
results = [],
|
||||
match;
|
||||
do {
|
||||
@@ -282,7 +273,7 @@ $tw.utils.parseStringArray = function(value) {
|
||||
}
|
||||
} while(match);
|
||||
return results;
|
||||
} else if ($tw.utils.isArray(value)) {
|
||||
} else if($tw.utils.isArray(value)) {
|
||||
return value;
|
||||
} else {
|
||||
return null;
|
||||
@@ -344,14 +335,35 @@ $tw.utils.resolvePath = function(sourcepath,rootpath) {
|
||||
};
|
||||
|
||||
/*
|
||||
Returns true if the `actual` version is greater than or equal to the `required` version. Both are in `x.y.z` format.
|
||||
Parse a semantic version string into its constituent parts
|
||||
*/
|
||||
$tw.utils.checkVersions = function(required,actual) {
|
||||
var targetVersion = required.split("."),
|
||||
currVersion = actual.split("."),
|
||||
diff = [parseInt(targetVersion[0],10) - parseInt(currVersion[0],10),
|
||||
parseInt(targetVersion[1],10) - parseInt(currVersion[1],10),
|
||||
parseInt(targetVersion[2],10) - parseInt(currVersion[2],10)];
|
||||
$tw.utils.parseVersion = function(version) {
|
||||
var match = /^((\d+)\.(\d+)\.(\d+))(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/.exec(version);
|
||||
if(match) {
|
||||
return {
|
||||
version: match[1],
|
||||
major: parseInt(match[2],10),
|
||||
minor: parseInt(match[3],10),
|
||||
patch: parseInt(match[4],10),
|
||||
prerelease: match[5],
|
||||
build: match[6]
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Returns true if the version string A is greater than the version string B
|
||||
*/
|
||||
$tw.utils.checkVersions = function(versionStringA,versionStringB) {
|
||||
var versionA = $tw.utils.parseVersion(versionStringA),
|
||||
versionB = $tw.utils.parseVersion(versionStringB),
|
||||
diff = [
|
||||
versionA.major - versionB.major,
|
||||
versionA.minor - versionB.minor,
|
||||
versionA.patch - versionB.patch
|
||||
];
|
||||
return (diff[0] > 0) ||
|
||||
(diff[0] === 0 && diff[1] > 0) ||
|
||||
(diff[0] === 0 && diff[1] === 0 && diff[2] > 0);
|
||||
@@ -427,11 +439,13 @@ Adds a new password prompt. Options are:
|
||||
submitText: text to use for submit button (defaults to "Login")
|
||||
serviceName: text of the human readable service name
|
||||
noUserName: set true to disable username prompt
|
||||
canCancel: set true to enable a cancel button (callback called with null)
|
||||
callback: function to be called on submission with parameter of object {username:,password:}. Callback must return `true` to remove the password prompt
|
||||
*/
|
||||
$tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
|
||||
// Create and add the prompt to the DOM
|
||||
var submitText = options.submitText || "Login",
|
||||
var self = this,
|
||||
submitText = options.submitText || "Login",
|
||||
dm = $tw.utils.domMaker,
|
||||
children = [dm("h1",{text: options.serviceName})];
|
||||
if(!options.noUserName) {
|
||||
@@ -444,6 +458,19 @@ $tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
|
||||
attributes: {type: "password", name: "password", placeholder: "Password"},
|
||||
"class": "input-small"
|
||||
}));
|
||||
if(options.canCancel) {
|
||||
children.push(dm("button",{
|
||||
text: "Cancel",
|
||||
"class": "btn",
|
||||
eventListeners: [{
|
||||
name: "click",
|
||||
handlerFunction: function(event) {
|
||||
self.removePrompt(promptInfo);
|
||||
options.callback(null);
|
||||
}
|
||||
}]
|
||||
}));
|
||||
}
|
||||
children.push(dm("button",{
|
||||
attributes: {type: "submit"},
|
||||
text: submitText,
|
||||
@@ -471,12 +498,7 @@ $tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
|
||||
// Call the callback
|
||||
if(options.callback(data)) {
|
||||
// Remove the prompt if the callback returned true
|
||||
var i = self.passwordPrompts.indexOf(promptInfo);
|
||||
if(i !== -1) {
|
||||
self.passwordPrompts.splice(i,1);
|
||||
promptInfo.form.parentNode.removeChild(promptInfo.form);
|
||||
self.setWrapperDisplay();
|
||||
}
|
||||
self.removePrompt(promptInfo);
|
||||
} else {
|
||||
// Clear the password if the callback returned false
|
||||
$tw.utils.each(form.elements,function(element) {
|
||||
@@ -499,17 +521,29 @@ $tw.utils.PasswordPrompt.prototype.createPrompt = function(options) {
|
||||
this.setWrapperDisplay();
|
||||
};
|
||||
|
||||
$tw.utils.PasswordPrompt.prototype.removePrompt = function(promptInfo) {
|
||||
var i = this.passwordPrompts.indexOf(promptInfo);
|
||||
if(i !== -1) {
|
||||
this.passwordPrompts.splice(i,1);
|
||||
promptInfo.form.parentNode.removeChild(promptInfo.form);
|
||||
this.setWrapperDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Crypto helper object for encrypted content. It maintains the password text in a closure, and provides methods to change
|
||||
the password, and to encrypt/decrypt a block of text
|
||||
*/
|
||||
$tw.utils.Crypto = function() {
|
||||
var sjcl = $tw.browser ? window.sjcl : require("./sjcl.js"),
|
||||
password = null,
|
||||
callSjcl = function(method,inputText) {
|
||||
currentPassword = null,
|
||||
callSjcl = function(method,inputText,password) {
|
||||
password = password || currentPassword;
|
||||
var outputText;
|
||||
try {
|
||||
outputText = sjcl[method](password,inputText);
|
||||
if(password) {
|
||||
outputText = sjcl[method](password,inputText);
|
||||
}
|
||||
} catch(ex) {
|
||||
console.log("Crypto error:" + ex);
|
||||
outputText = null;
|
||||
@@ -517,22 +551,22 @@ $tw.utils.Crypto = function() {
|
||||
return outputText;
|
||||
};
|
||||
this.setPassword = function(newPassword) {
|
||||
password = newPassword;
|
||||
currentPassword = newPassword;
|
||||
this.updateCryptoStateTiddler();
|
||||
};
|
||||
this.updateCryptoStateTiddler = function() {
|
||||
if($tw.wiki && $tw.wiki.addTiddler) {
|
||||
$tw.wiki.addTiddler(new $tw.Tiddler({title: "$:/isEncrypted", text: password ? "yes" : "no"}));
|
||||
$tw.wiki.addTiddler(new $tw.Tiddler({title: "$:/isEncrypted", text: currentPassword ? "yes" : "no"}));
|
||||
}
|
||||
};
|
||||
this.hasPassword = function() {
|
||||
return !!password;
|
||||
return !!currentPassword;
|
||||
}
|
||||
this.encrypt = function(text) {
|
||||
return callSjcl("encrypt",text);
|
||||
this.encrypt = function(text,password) {
|
||||
return callSjcl("encrypt",text,password);
|
||||
};
|
||||
this.decrypt = function(text) {
|
||||
return callSjcl("decrypt",text);
|
||||
this.decrypt = function(text,password) {
|
||||
return callSjcl("decrypt",text,password);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -758,7 +792,9 @@ $tw.Wiki.prototype.addTiddler = function(tiddler) {
|
||||
if(!(tiddler instanceof $tw.Tiddler)) {
|
||||
tiddler = new $tw.Tiddler(tiddler);
|
||||
}
|
||||
this.tiddlers[tiddler.fields.title] = tiddler;
|
||||
if(tiddler.fields.title) {
|
||||
this.tiddlers[tiddler.fields.title] = tiddler;
|
||||
}
|
||||
};
|
||||
|
||||
$tw.Wiki.prototype.addTiddlers = function(tiddlers) {
|
||||
@@ -838,10 +874,12 @@ $tw.Wiki.prototype.unpackPluginTiddlers = function() {
|
||||
// Extract the constituent tiddlers
|
||||
$tw.utils.each(pluginInfo.tiddlers,function(constituentTiddler,constituentTitle) {
|
||||
// Save the tiddler object
|
||||
self.shadowTiddlers[constituentTitle] = {
|
||||
source: tiddler.fields.title,
|
||||
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
|
||||
};
|
||||
if(constituentTitle) {
|
||||
self.shadowTiddlers[constituentTitle] = {
|
||||
source: tiddler.fields.title,
|
||||
tiddler: new $tw.Tiddler(constituentTiddler,{title: constituentTitle})
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -890,7 +928,7 @@ $tw.Wiki.prototype.getTiddler = function(title) {
|
||||
var t = this.tiddlers[title];
|
||||
if(t instanceof $tw.Tiddler) {
|
||||
return t;
|
||||
} else if($tw.utils.hop(this.shadowTiddlers,title)) {
|
||||
} else if(title !== undefined && $tw.utils.hop(this.shadowTiddlers,title)) {
|
||||
return this.shadowTiddlers[title].tiddler;
|
||||
} else {
|
||||
return undefined;
|
||||
@@ -1075,7 +1113,7 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
|
||||
}
|
||||
});
|
||||
|
||||
$tw.loadTiddlers = function() {
|
||||
$tw.loadTiddlersBrowser = function() {
|
||||
// In the browser, we load tiddlers from certain elements
|
||||
var containerIds = [
|
||||
"libraryModules",
|
||||
@@ -1110,6 +1148,12 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) {
|
||||
callback();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////// Node definitions
|
||||
|
||||
if($tw.node) {
|
||||
|
||||
/*
|
||||
Load the tiddlers contained in a particular file (and optionally extract fields from the accompanying .meta file) returned as {filepath:,type:,tiddlers:[],hasMetaFile:}
|
||||
*/
|
||||
@@ -1131,11 +1175,18 @@ $tw.loadTiddlersFromFile = function(filepath,fields) {
|
||||
return {filepath: filepath, type: type, tiddlers: tiddlers, hasMetaFile: !!metadata};
|
||||
};
|
||||
|
||||
/*
|
||||
A default set of files for TiddlyWiki to ignore during load.
|
||||
This matches what NPM ignores, and adds "*.meta" to ignore tiddler
|
||||
metadata files.
|
||||
*/
|
||||
$tw.boot.excludeRegExp = /^\.DS_Store$|^.*\.meta$|^\..*\.swp$|^\._.*$|^\.git$|^\.hg$|^\.lock-wscript$|^\.svn$|^\.wafpickle-.*$|^CVS$|^npm-debug\.log$/;
|
||||
|
||||
/*
|
||||
Load all the tiddlers recursively from a directory, including honouring `tiddlywiki.files` files for drawing in external files. Returns an array of {filepath:,type:,tiddlers: [{..fields...}],hasMetaFile:}. Note that no file information is returned for externally loaded tiddlers, just the `tiddlers` property.
|
||||
*/
|
||||
$tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
|
||||
excludeRegExp = excludeRegExp || /^\.DS_Store$|.meta$/;
|
||||
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
|
||||
var tiddlers = [];
|
||||
if(fs.existsSync(filepath)) {
|
||||
var stat = fs.statSync(filepath);
|
||||
@@ -1177,7 +1228,7 @@ $tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
|
||||
Load the tiddlers from a plugin folder, and package them up into a proper JSON plugin tiddler
|
||||
*/
|
||||
$tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
||||
excludeRegExp = excludeRegExp || /^\.DS_Store$|.meta$/;
|
||||
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
|
||||
var stat, files, pluginInfo, pluginTiddlers = [], f, file, titlePrefix, t;
|
||||
if(fs.existsSync(filepath)) {
|
||||
stat = fs.statSync(filepath);
|
||||
@@ -1198,7 +1249,9 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
||||
// Save the plugin tiddlers into the plugin info
|
||||
pluginInfo.tiddlers = pluginInfo.tiddlers || {};
|
||||
for(t=0; t<pluginTiddlers.length; t++) {
|
||||
pluginInfo.tiddlers[pluginTiddlers[t].title] = pluginTiddlers[t];
|
||||
if(pluginTiddlers[t].title) {
|
||||
pluginInfo.tiddlers[pluginTiddlers[t].title] = pluginTiddlers[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1211,13 +1264,14 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
||||
var fields = {
|
||||
title: pluginInfo.title,
|
||||
type: "application/json",
|
||||
text: JSON.stringify(pluginInfo,null,4),
|
||||
text: JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4),
|
||||
"plugin-priority": pluginInfo["plugin-priority"],
|
||||
"name": pluginInfo["name"],
|
||||
"version": pluginInfo["version"],
|
||||
"thumbnail": pluginInfo["thumbnail"],
|
||||
"description": pluginInfo["description"],
|
||||
"plugin-type": pluginInfo["plugin-type"] || "plugin"
|
||||
"plugin-type": pluginInfo["plugin-type"] || "plugin",
|
||||
"dependents": $tw.utils.stringifyList(pluginInfo["dependents"] || [])
|
||||
}
|
||||
return fields;
|
||||
} else {
|
||||
@@ -1225,6 +1279,20 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Fallback tiddlywiki.info content
|
||||
*/
|
||||
$tw.boot.defaultWikiInfo = {
|
||||
"plugins": [
|
||||
"tiddlywiki/tiddlyweb",
|
||||
"tiddlywiki/filesystem"
|
||||
],
|
||||
"themes": [
|
||||
"tiddlywiki/vanilla",
|
||||
"tiddlywiki/snowwhite"
|
||||
]
|
||||
};
|
||||
|
||||
/*
|
||||
path: path of wiki directory
|
||||
parentPaths: array of parent paths that we mustn't recurse into
|
||||
@@ -1232,13 +1300,14 @@ parentPaths: array of parent paths that we mustn't recurse into
|
||||
$tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
|
||||
parentPaths = parentPaths || [];
|
||||
var wikiInfoPath = path.resolve(wikiPath,$tw.config.wikiInfo),
|
||||
wikiInfo = {},
|
||||
wikiInfo,
|
||||
pluginFields;
|
||||
// Bail if we don't have a wiki info file
|
||||
if(!fs.existsSync(wikiInfoPath)) {
|
||||
$tw.utils.error("Missing tiddlywiki.info file at " + wikiPath);
|
||||
if(fs.existsSync(wikiInfoPath)) {
|
||||
wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8"));
|
||||
} else {
|
||||
wikiInfo = $tw.boot.defaultWikiInfo;
|
||||
}
|
||||
wikiInfo = JSON.parse(fs.readFileSync(wikiInfoPath,"utf8"));
|
||||
// Load any parent wikis
|
||||
if(wikiInfo.includeWikis) {
|
||||
parentPaths = parentPaths.slice(0);
|
||||
@@ -1313,7 +1382,7 @@ $tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
|
||||
return wikiInfo;
|
||||
};
|
||||
|
||||
$tw.loadTiddlers = function() {
|
||||
$tw.loadTiddlersNode = function() {
|
||||
// Load the boot tiddlers
|
||||
$tw.utils.each($tw.loadTiddlersFromPath($tw.boot.bootPath),function(tiddlerFile) {
|
||||
$tw.wiki.addTiddlers(tiddlerFile.tiddlers);
|
||||
@@ -1326,12 +1395,17 @@ $tw.loadTiddlers = function() {
|
||||
}
|
||||
};
|
||||
|
||||
// End of if(!$tw.browser)
|
||||
// End of if($tw.node)
|
||||
}
|
||||
|
||||
/////////////////////////// Main startup function called once tiddlers have been decrypted
|
||||
|
||||
$tw.boot.startup = function() {
|
||||
/*
|
||||
Startup TiddlyWiki. Options are:
|
||||
readBrowserTiddlers: whether to read tiddlers from the HTML file we're executing within; if not, tiddlers are read from the file system with Node.js APIs
|
||||
*/
|
||||
$tw.boot.startup = function(options) {
|
||||
options = options || {};
|
||||
// Initialise some more $tw properties
|
||||
$tw.utils.deepDefaults($tw,{
|
||||
modules: { // Information about each module
|
||||
@@ -1350,7 +1424,7 @@ $tw.boot.startup = function() {
|
||||
contentTypeInfo: {} // Map type to {encoding:,extension:}
|
||||
}
|
||||
});
|
||||
if(!$tw.browser) {
|
||||
if(!options.readBrowserTiddlers) {
|
||||
// For writable tiddler files, a hashmap of title to {filepath:,type:,hasMetaFile:}
|
||||
$tw.boot.files = {};
|
||||
// System paths and filenames
|
||||
@@ -1369,7 +1443,7 @@ $tw.boot.startup = function() {
|
||||
$tw.boot.wikiPath = process.cwd();
|
||||
}
|
||||
// Read package info
|
||||
$tw.packageInfo = require("../package");
|
||||
$tw.packageInfo = require("../package.json");
|
||||
// Check node version number
|
||||
if($tw.utils.checkVersions($tw.packageInfo.engines.node.substr(2),process.version.substr(1))) {
|
||||
$tw.utils.error("TiddlyWiki5 requires node.js version " + $tw.packageInfo.engines.node);
|
||||
@@ -1390,6 +1464,7 @@ $tw.boot.startup = function() {
|
||||
$tw.utils.registerFileType("image/png","base64",".png");
|
||||
$tw.utils.registerFileType("image/gif","base64",".gif");
|
||||
$tw.utils.registerFileType("image/svg+xml","utf8",".svg");
|
||||
$tw.utils.registerFileType("image/x-icon","base64",".ico");
|
||||
$tw.utils.registerFileType("application/font-woff","base64",".woff");
|
||||
// Create the wiki store for the app
|
||||
$tw.wiki = new $tw.Wiki();
|
||||
@@ -1399,7 +1474,11 @@ $tw.boot.startup = function() {
|
||||
$tw.Wiki.tiddlerDeserializerModules = {};
|
||||
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
|
||||
// Load tiddlers
|
||||
$tw.loadTiddlers();
|
||||
if(options.readBrowserTiddlers) {
|
||||
$tw.loadTiddlersBrowser();
|
||||
} else {
|
||||
$tw.loadTiddlersNode();
|
||||
}
|
||||
// Unpack plugin tiddlers
|
||||
$tw.wiki.registerPluginTiddlers("plugin");
|
||||
$tw.wiki.unpackPluginTiddlers();
|
||||
@@ -1408,7 +1487,9 @@ $tw.boot.startup = function() {
|
||||
// And any modules within plugins
|
||||
$tw.wiki.defineShadowModules();
|
||||
// Make sure the crypto state tiddler is up to date
|
||||
$tw.crypto.updateCryptoStateTiddler();
|
||||
if($tw.crypto) {
|
||||
$tw.crypto.updateCryptoStateTiddler();
|
||||
}
|
||||
// Run any startup modules
|
||||
$tw.modules.forEachModuleOfType("startup",function(title,module) {
|
||||
if(module.startup) {
|
||||
@@ -1429,13 +1510,15 @@ $tw.boot.boot = function() {
|
||||
// Preload any encrypted tiddlers
|
||||
$tw.boot.decryptEncryptedTiddlers(function() {
|
||||
// Startup
|
||||
$tw.boot.startup();
|
||||
$tw.boot.startup({
|
||||
readBrowserTiddlers: !!$tw.browser
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/////////////////////////// Autoboot in the browser
|
||||
|
||||
if($tw.browser) {
|
||||
if($tw.browser && !$tw.boot.suppressBoot) {
|
||||
$tw.boot.boot();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,12 @@ var _bootprefix = (function($tw) {
|
||||
|
||||
"use strict";
|
||||
|
||||
$tw = $tw || {browser: typeof(window) !== "undefined" ? {} : null};
|
||||
$tw = $tw || {};
|
||||
|
||||
// Detect platforms
|
||||
$tw.browser = typeof(window) !== "undefined" ? {} : null;
|
||||
$tw.node = typeof(process) === "object" ? {} : null;
|
||||
$tw.nodeWebKit = $tw.node && global.window && global.window.nwDispatcher ? {} : null;
|
||||
|
||||
/*
|
||||
Information about each module is kept in an object with these members:
|
||||
@@ -92,6 +97,3 @@ if(typeof(exports) === "undefined") {
|
||||
// Export functionality as a module
|
||||
exports.bootprefix = _bootprefix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
3
core/config/editor-type-mappings/image-gif.tid
Normal file
3
core/config/editor-type-mappings/image-gif.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/image/gif
|
||||
|
||||
bitmap
|
||||
3
core/config/editor-type-mappings/image-jpeg.tid
Normal file
3
core/config/editor-type-mappings/image-jpeg.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/image/jpeg
|
||||
|
||||
bitmap
|
||||
3
core/config/editor-type-mappings/image-jpg.tid
Normal file
3
core/config/editor-type-mappings/image-jpg.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/image/jpg
|
||||
|
||||
bitmap
|
||||
3
core/config/editor-type-mappings/image-png.tid
Normal file
3
core/config/editor-type-mappings/image-png.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/image/png
|
||||
|
||||
bitmap
|
||||
3
core/config/editor-type-mappings/image-x-icon.tid
Normal file
3
core/config/editor-type-mappings/image-x-icon.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/image/x-icon
|
||||
|
||||
bitmap
|
||||
3
core/config/editor-type-mappings/text-vnd-tiddlywiki.tid
Normal file
3
core/config/editor-type-mappings/text-vnd-tiddlywiki.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/config/EditorTypeMappings/text/vnd.tiddlywiki
|
||||
|
||||
text
|
||||
@@ -4,7 +4,7 @@ type: text/plain
|
||||
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
|
||||
|
||||
Copyright © Jeremy Ruston 2004-2007
|
||||
Copyright © UnaMesa Association 2007-2013
|
||||
Copyright © UnaMesa Association 2007-2014
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
3
core/docs/types/image_x-icon.tid
Normal file
3
core/docs/types/image_x-icon.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/image/x-icon
|
||||
description: ICO format icon file
|
||||
name: image/x-icon
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/docs/types/text/vnd.tiddlywiki
|
||||
description: TW5 wikitext
|
||||
description: TiddlyWiki version 5 wikitext
|
||||
name: text/vnd.tiddlywiki
|
||||
|
||||
3
core/docs/types/text_x-tiddlywiki.tid
Normal file
3
core/docs/types/text_x-tiddlywiki.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/text/x-tiddlywiki
|
||||
description: TiddlyWiki Classic wikitext
|
||||
name: text/x-tiddlywiki
|
||||
@@ -42,7 +42,7 @@ Command.prototype.execute = function() {
|
||||
$tw.utils.each(tiddlers,function(title) {
|
||||
var parser = wiki.parseTiddler(template),
|
||||
widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});
|
||||
var container = $tw.document.createElement("div");
|
||||
var container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
var text = type === "text/html" ? container.innerHTML : container.textContent;
|
||||
fs.writeFileSync(path.resolve(pathname,encodeURIComponent(title) + extension),text,"utf8");
|
||||
|
||||
46
core/modules/commands/savetiddler.js
Normal file
46
core/modules/commands/savetiddler.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/*\
|
||||
title: $:/core/modules/commands/savetiddler.js
|
||||
type: application/javascript
|
||||
module-type: command
|
||||
|
||||
Command to save the content of a tiddler to a file
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.info = {
|
||||
name: "savetiddler",
|
||||
synchronous: false
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
this.params = params;
|
||||
this.commander = commander;
|
||||
this.callback = callback;
|
||||
};
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
if(this.params.length < 2) {
|
||||
return "Missing filename";
|
||||
}
|
||||
var self = this,
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
title = this.params[0],
|
||||
filename = this.params[1],
|
||||
tiddler = this.commander.wiki.getTiddler(title),
|
||||
type = tiddler.fields.type || "text/vnd.tiddlywiki",
|
||||
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"};
|
||||
fs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {
|
||||
self.callback(err);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
|
||||
exports.Command = Command;
|
||||
|
||||
})();
|
||||
@@ -79,7 +79,7 @@ SimpleServer.prototype.checkCredentials = function(request,incomingUsername,inco
|
||||
}
|
||||
}
|
||||
|
||||
SimpleServer.prototype.listen = function(port) {
|
||||
SimpleServer.prototype.listen = function(port,host) {
|
||||
var self = this;
|
||||
http.createServer(function(request,response) {
|
||||
// Compose the state object
|
||||
@@ -95,9 +95,8 @@ SimpleServer.prototype.listen = function(port) {
|
||||
if(username && password) {
|
||||
// Check they match
|
||||
if(self.checkCredentials(request,username,password) !== "ALLOWED") {
|
||||
response.setHeader("WWW-Authenticate", 'Basic realm="Admin Area"');
|
||||
response.writeHead(401,"Authentication required",{
|
||||
"WWW-Authenticate": 'Basic realm="TiddlyWiki5"'
|
||||
"WWW-Authenticate": 'Basic realm="Please provide your username and password to login to TiddlyWiki5"'
|
||||
});
|
||||
response.end();
|
||||
return;
|
||||
@@ -126,7 +125,7 @@ SimpleServer.prototype.listen = function(port) {
|
||||
});
|
||||
break;
|
||||
}
|
||||
}).listen(port);
|
||||
}).listen(port,host);
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
@@ -197,13 +196,22 @@ var Command = function(params,commander,callback) {
|
||||
response.end(text,"utf8");
|
||||
}
|
||||
});
|
||||
this.server.addRoute({
|
||||
method: "GET",
|
||||
path: /^\/favicon.ico$/,
|
||||
handler: function(request,response,state) {
|
||||
response.writeHead(200, {"Content-Type": "image/x-icon"});
|
||||
var buffer = state.wiki.getTiddlerText("$:/favicon.ico","");
|
||||
response.end(buffer,"base64");
|
||||
}
|
||||
});
|
||||
this.server.addRoute({
|
||||
method: "GET",
|
||||
path: /^\/recipes\/default\/tiddlers.json$/,
|
||||
handler: function(request,response,state) {
|
||||
response.writeHead(200, {"Content-Type": "application/json"});
|
||||
var tiddlers = [];
|
||||
state.wiki.forEachTiddler("title",function(title,tiddler) {
|
||||
state.wiki.forEachTiddler({sortField: "title"},function(title,tiddler) {
|
||||
var tiddlerFields = {};
|
||||
$tw.utils.each(tiddler.fields,function(field,name) {
|
||||
if(name !== "text") {
|
||||
@@ -255,8 +263,9 @@ Command.prototype.execute = function() {
|
||||
rootTiddler = this.params[1] || "$:/core/save/all",
|
||||
renderType = this.params[2] || "text/plain",
|
||||
serveType = this.params[3] || "text/html",
|
||||
username = this.params[4] || "ANONYMOUS",
|
||||
password = this.params[5];
|
||||
username = this.params[4],
|
||||
password = this.params[5],
|
||||
host = this.params[6] || "127.0.0.1";
|
||||
this.server.set({
|
||||
rootTiddler: rootTiddler,
|
||||
renderType: renderType,
|
||||
@@ -264,10 +273,9 @@ Command.prototype.execute = function() {
|
||||
username: username,
|
||||
password: password
|
||||
});
|
||||
this.server.listen(port);
|
||||
if(this.commander.verbose) {
|
||||
console.log("Serving on port " + port);
|
||||
}
|
||||
this.server.listen(port,host);
|
||||
console.log("Serving on " + host + ":" + port);
|
||||
console.log("(press ctrl-C to exit)");
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,30 +36,35 @@ var parseTiddlerDiv = function(text /* [,fields] */) {
|
||||
}
|
||||
}
|
||||
// Parse the DIV body
|
||||
var divRegExp = /^\s*<div\s+([^>]*)>((?:\s|\S)*)<\/div>\s*$/gi,
|
||||
subDivRegExp = /^\s*<pre>((?:\s|\S)*)<\/pre>\s*$/gi,
|
||||
attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi,
|
||||
match = divRegExp.exec(text);
|
||||
var startRegExp = /^\s*<div\s+([^>]*)>(\s*<pre>)?/gi,
|
||||
endRegExp,
|
||||
match = startRegExp.exec(text);
|
||||
if(match) {
|
||||
var subMatch = subDivRegExp.exec(match[2]); // Body of the <DIV> tag
|
||||
if(subMatch) {
|
||||
result.text = subMatch[1];
|
||||
// Old-style DIVs don't have the <pre> tag
|
||||
if(match[2]) {
|
||||
endRegExp = /<\/pre>\s*<\/div>\s*$/gi;
|
||||
} else {
|
||||
result.text = match[2];
|
||||
endRegExp = /<\/div>\s*$/gi;
|
||||
}
|
||||
var endMatch = endRegExp.exec(text);
|
||||
if(endMatch) {
|
||||
// Extract the text
|
||||
result.text = text.substring(match.index + match[0].length,endMatch.index);
|
||||
// Process the attributes
|
||||
var attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi,
|
||||
attrMatch;
|
||||
do {
|
||||
attrMatch = attrRegExp.exec(match[1]);
|
||||
if(attrMatch) {
|
||||
var name = attrMatch[1];
|
||||
var value = attrMatch[2];
|
||||
result[name] = value;
|
||||
}
|
||||
} while(attrMatch);
|
||||
return result;
|
||||
}
|
||||
var attrMatch;
|
||||
do {
|
||||
attrMatch = attrRegExp.exec(match[1]);
|
||||
if(attrMatch) {
|
||||
var name = attrMatch[1];
|
||||
var value = attrMatch[2];
|
||||
result[name] = value;
|
||||
}
|
||||
} while(attrMatch);
|
||||
return result;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
exports["application/x-tiddler-html-div"] = function(text,fields) {
|
||||
@@ -95,11 +100,26 @@ exports["text/html"] = function(text,fields) {
|
||||
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
|
||||
match = storeAreaMarkerRegExp.exec(text);
|
||||
if(match) {
|
||||
// If so, it's either a classic TiddlyWiki file or a TW5 file
|
||||
return deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
|
||||
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
|
||||
// First read the normal tiddlers
|
||||
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
|
||||
// Then any system tiddlers
|
||||
var systemAreaMarkerRegExp = /<div id=["']?systemArea['"]?( style=["']?display:none;["']?)?>/gi,
|
||||
sysMatch = systemAreaMarkerRegExp.exec(text);
|
||||
if(sysMatch) {
|
||||
results.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));
|
||||
}
|
||||
return results
|
||||
} else {
|
||||
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
|
||||
return deserializeHtmlFile(text,fields);
|
||||
// Check whether we've got an encrypted file
|
||||
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
|
||||
if(encryptedStoreArea) {
|
||||
// If so, attempt to decrypt it using the current password
|
||||
return $tw.utils.decryptStoreArea(encryptedStoreArea);
|
||||
} else {
|
||||
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
|
||||
return deserializeHtmlFile(text,fields);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,31 +33,55 @@ function parseFilterOperation(operators,filterString,p) {
|
||||
operator.prefix = filterString.charAt(p++);
|
||||
}
|
||||
// Get the operator name
|
||||
bracketPos = filterString.indexOf("[",p);
|
||||
curlyBracketPos = filterString.indexOf("{",p);
|
||||
if((bracketPos === -1) && (curlyBracketPos === -1)) {
|
||||
var nextBracketPos = filterString.substring(p).search(/[\[\{\/]/);
|
||||
if(nextBracketPos === -1) {
|
||||
throw "Missing [ in filter expression";
|
||||
}
|
||||
if(bracketPos === -1 || (curlyBracketPos !== -1 && curlyBracketPos < bracketPos)) {
|
||||
// Curly brackets
|
||||
operator.indirect = true;
|
||||
operator.operator = filterString.substring(p,curlyBracketPos);
|
||||
p = curlyBracketPos + 1;
|
||||
} else {
|
||||
// Square brackets
|
||||
operator.operator = filterString.substring(p,bracketPos);
|
||||
p = bracketPos + 1;
|
||||
nextBracketPos += p;
|
||||
var bracket = filterString.charAt(nextBracketPos);
|
||||
operator.operator = filterString.substring(p,nextBracketPos);
|
||||
|
||||
// Any suffix?
|
||||
var colon = operator.operator.indexOf(':');
|
||||
if(colon > -1) {
|
||||
operator.suffix = operator.operator.substring(colon + 1);
|
||||
operator.operator = operator.operator.substring(0,colon) || "field";
|
||||
}
|
||||
if(operator.operator === "") {
|
||||
// Empty operator means: title
|
||||
else if(operator.operator === "") {
|
||||
operator.operator = "title";
|
||||
}
|
||||
// Get the operand
|
||||
bracketPos = filterString.indexOf(operator.indirect ? "}" : "]",p);
|
||||
if(bracketPos === -1) {
|
||||
|
||||
p = nextBracketPos + 1;
|
||||
switch (bracket) {
|
||||
case '{': // Curly brackets
|
||||
operator.indirect = true;
|
||||
nextBracketPos = filterString.indexOf('}',p);
|
||||
break;
|
||||
case '[': // Square brackets
|
||||
nextBracketPos = filterString.indexOf(']',p);
|
||||
break;
|
||||
case '/': // regexp brackets
|
||||
var rex = /^((?:[^\\\/]*|\\.))*\/(?:\(([mygi]+)\))?/g,
|
||||
rexMatch = rex.exec(filterString.substring(p));
|
||||
if(rexMatch) {
|
||||
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
|
||||
nextBracketPos = p + rex.lastIndex - 1;
|
||||
}
|
||||
else {
|
||||
throw "Unterminated regular expression in filter expression";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(nextBracketPos === -1) {
|
||||
throw "Missing closing bracket in filter expression";
|
||||
}
|
||||
operator.operand = filterString.substring(p,bracketPos);
|
||||
p = bracketPos + 1;
|
||||
if(!operator.regexp) {
|
||||
operator.operand = filterString.substring(p,nextBracketPos);
|
||||
}
|
||||
p = nextBracketPos + 1;
|
||||
|
||||
// Push this operator
|
||||
operators.push(operator);
|
||||
} while(filterString.charAt(p) !== "]");
|
||||
@@ -161,7 +185,9 @@ exports.compileFilter = function(filterString) {
|
||||
results = operatorFunction(accumulator,{
|
||||
operator: operator.operator,
|
||||
operand: operand,
|
||||
prefix: operator.prefix
|
||||
prefix: operator.prefix,
|
||||
suffix: operator.suffix,
|
||||
regexp: operator.regexp
|
||||
},{
|
||||
wiki: self,
|
||||
currTiddlerTitle: currTiddlerTitle
|
||||
|
||||
@@ -16,12 +16,19 @@ Filter operator for comparing fields for equality
|
||||
Export our filter function
|
||||
*/
|
||||
exports.field = function(source,operator,options) {
|
||||
var results = [];
|
||||
var results = [],
|
||||
fieldname = (operator.suffix || operator.operator).toLowerCase();
|
||||
// Function to check an individual title
|
||||
function checkTiddler(title) {
|
||||
var tiddler = options.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
var match = tiddler.getFieldString(operator.operator) === operator.operand;
|
||||
var match,
|
||||
text = tiddler.getFieldString(fieldname);
|
||||
if(operator.regexp) {
|
||||
match = !!operator.regexp.exec(text);
|
||||
} else {
|
||||
match = text === operator.operand;
|
||||
}
|
||||
if(operator.prefix === "!") {
|
||||
match = !match;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ exports.has = function(source,operator,options) {
|
||||
function checkTiddler(title) {
|
||||
var tiddler = options.wiki.getTiddler(title);
|
||||
if(tiddler) {
|
||||
var match = $tw.utils.hop(tiddler.fields,operator.operand);
|
||||
var match = $tw.utils.hop(tiddler.fields,operator.operand) && tiddler.fields[operator.operand] !== "";
|
||||
if(operator.prefix === "!") {
|
||||
match = !match;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ Export our filter function
|
||||
*/
|
||||
exports.list = function(source,operator,options) {
|
||||
var results = [],
|
||||
list = options.wiki.getTiddlerList(operator.operand);
|
||||
tr = $tw.utils.parseTextReference(operator.operand),
|
||||
list = options.wiki.getTiddlerList(tr.title,tr.field,tr.index);
|
||||
function checkTiddler(title) {
|
||||
var match = list.indexOf(title) !== -1;
|
||||
if(operator.prefix === "!") {
|
||||
|
||||
87
core/modules/filters/listops.js
Normal file
87
core/modules/filters/listops.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/listops.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operators for manipulating the current selection list
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Reverse list
|
||||
*/
|
||||
exports.reverse = function(source,operator,options) {
|
||||
var results = [];
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
$tw.utils.each(source,function(title) {
|
||||
results.unshift(title);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
/*
|
||||
First entry/entries in list
|
||||
*/
|
||||
exports.first = function(source,operator,options) {
|
||||
var count = parseInt(operator.operand) || 1;
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
return source.slice(0,Math.min(count,source.length));
|
||||
};
|
||||
|
||||
/*
|
||||
Last entry/entries in list
|
||||
*/
|
||||
exports.last = function(source,operator,options) {
|
||||
var count = parseInt(operator.operand) || 1;
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
return source.slice(-count);
|
||||
};
|
||||
|
||||
/*
|
||||
All but the first entry/entries of the list
|
||||
*/
|
||||
exports.rest = function(source,operator,options) {
|
||||
var count = parseInt(operator.operand) || 1;
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
return source.slice(count);
|
||||
};
|
||||
exports.butfirst = exports.rest;
|
||||
exports.bf = exports.rest;
|
||||
|
||||
/*
|
||||
All but the last entry/entries of the list
|
||||
*/
|
||||
exports.butlast = function(source,operator,options) {
|
||||
var count = parseInt(operator.operand) || 1;
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
return source.slice(0,-count);
|
||||
};
|
||||
exports.bl = exports.butlast;
|
||||
|
||||
/*
|
||||
The nth member of the list
|
||||
*/
|
||||
exports.nth = function(source,operator,options) {
|
||||
var count = parseInt(operator.operand) || 1;
|
||||
if(!$tw.utils.isArray(source)) {
|
||||
source = Object.keys(source).sort();
|
||||
}
|
||||
return source.slice(count-1,count);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -16,6 +16,30 @@ Filter operator for sorting
|
||||
Export our filter function
|
||||
*/
|
||||
exports.sort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!",false,false);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsort = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!",false,true);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.sortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!",true,false);
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.nsortcs = function(source,operator,options) {
|
||||
var results = prepare_results(source);
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!",true,true);
|
||||
return results;
|
||||
};
|
||||
|
||||
var prepare_results = function (source) {
|
||||
var results;
|
||||
if($tw.utils.isArray(source)) {
|
||||
results = source;
|
||||
@@ -25,8 +49,7 @@ exports.sort = function(source,operator,options) {
|
||||
results.push(title);
|
||||
});
|
||||
}
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!");
|
||||
return results;
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/sortcs.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for case-sensitive sorting
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.sortcs = function(source,operator,options) {
|
||||
var results;
|
||||
if($tw.utils.isArray(source)) {
|
||||
results = source;
|
||||
} else {
|
||||
results = [];
|
||||
$tw.utils.each(source,function(element,title) {
|
||||
results.push(title);
|
||||
});
|
||||
}
|
||||
options.wiki.sortTiddlers(results,operator.operand,operator.prefix === "!",true);
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -38,6 +38,7 @@ exports["image/jpeg"] = ImageParser;
|
||||
exports["image/png"] = ImageParser;
|
||||
exports["image/gif"] = ImageParser;
|
||||
exports["application/pdf"] = ImageParser;
|
||||
exports["image/x-icon"] = ImageParser;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ exports["text/x-tiddlywiki"] = TextParser;
|
||||
exports["application/javascript"] = TextParser;
|
||||
exports["application/json"] = TextParser;
|
||||
exports["text/css"] = TextParser;
|
||||
exports["application/x-tiddler-dictionary"] = TextParser;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
@@ -23,14 +23,15 @@ exports.types = {block: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /```\r?\n/mg;
|
||||
// Regexp to match and get language if defined
|
||||
this.matchRegExp = /```([\w-]*)\r?\n/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var reEnd = /(\r?\n```$)/mg;
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
// Look for the end of the block
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
@@ -43,14 +44,14 @@ exports.parse = function() {
|
||||
text = this.parser.source.substr(this.parser.pos);
|
||||
this.parser.pos = this.parser.sourceLength;
|
||||
}
|
||||
// Return the pre element
|
||||
// Return the $codeblock widget
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "pre",
|
||||
children: [{
|
||||
type: "text",
|
||||
text: text
|
||||
}]
|
||||
type: "element",
|
||||
tag: "$codeblock",
|
||||
attributes: {
|
||||
code: {type: "string", value: text},
|
||||
language: {type: "string", value: this.match[1]}
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ Wiki text inline rule for code runs. For example:
|
||||
|
||||
```
|
||||
This is a `code run`.
|
||||
This is another ``code run``
|
||||
```
|
||||
|
||||
\*/
|
||||
@@ -22,13 +23,13 @@ exports.types = {inline: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /`/mg;
|
||||
this.matchRegExp = /(``?)/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
var reEnd = /`/mg;
|
||||
var reEnd = new RegExp(this.match[1], "mg");
|
||||
// Look for the end marker
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source),
|
||||
|
||||
58
core/modules/parsers/wikiparser/rules/hardlinebreaks.js
Normal file
58
core/modules/parsers/wikiparser/rules/hardlinebreaks.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki text inline rule for marking areas with hard line breaks. For example:
|
||||
|
||||
```
|
||||
"""
|
||||
This is some text
|
||||
That is set like
|
||||
It is a Poem
|
||||
When it is
|
||||
Clearly
|
||||
Not
|
||||
"""
|
||||
```
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "hardlinebreaks";
|
||||
exports.types = {inline: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /"""(?:\r?\n)?/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var reEnd = /(""")|(\r?\n)/mg,
|
||||
tree = [];
|
||||
// Move past the match
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
do {
|
||||
// Parse the run up to the terminator
|
||||
tree.push.apply(tree,this.parser.parseInlineRun(reEnd,{eatTerminator: false}));
|
||||
// Redo the terminator match
|
||||
reEnd.lastIndex = this.parser.pos;
|
||||
var match = reEnd.exec(this.parser.source);
|
||||
if(match) {
|
||||
this.parser.pos = reEnd.lastIndex;
|
||||
// Add a line break if the terminator was a line break
|
||||
if(match[2]) {
|
||||
tree.push({type: "element", tag: "br"});
|
||||
}
|
||||
}
|
||||
} while(match && !match[1]);
|
||||
// Return the nodes
|
||||
return tree;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -22,7 +22,7 @@ exports.types = {block: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /-{3,}\r?\n/mg;
|
||||
this.matchRegExp = /-{3,}\r?(?:\n|$)/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
|
||||
@@ -52,14 +52,15 @@ exports.types = {block: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /([\*#;:]+)/mg;
|
||||
this.matchRegExp = /([\*#;:>]+)/mg;
|
||||
};
|
||||
|
||||
var listTypes = {
|
||||
"*": {listTag: "ul", itemTag: "li"},
|
||||
"#": {listTag: "ol", itemTag: "li"},
|
||||
";": {listTag: "dl", itemTag: "dt"},
|
||||
":": {listTag: "dl", itemTag: "dd"}
|
||||
":": {listTag: "dl", itemTag: "dd"},
|
||||
">": {listTag: "blockquote", itemTag: "p"}
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -71,7 +72,7 @@ exports.parse = function() {
|
||||
// Cycle through the items in the list
|
||||
while(true) {
|
||||
// Match the list marker
|
||||
var reMatch = /([\*#;:]+)/mg;
|
||||
var reMatch = /([\*#;:>]+)/mg;
|
||||
reMatch.lastIndex = this.parser.pos;
|
||||
var match = reMatch.exec(this.parser.source);
|
||||
if(!match || match.index !== this.parser.pos) {
|
||||
|
||||
93
core/modules/parsers/wikiparser/rules/quoteblock.js
Normal file
93
core/modules/parsers/wikiparser/rules/quoteblock.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/quoteblock.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki text rule for quote blocks. For example:
|
||||
|
||||
```
|
||||
<<<.optionalClass(es) optional cited from
|
||||
a quote
|
||||
<<<
|
||||
|
||||
<<<.optionalClass(es)
|
||||
a quote
|
||||
<<< optional cited from
|
||||
```
|
||||
|
||||
Quotes can be quoted by putting more <s
|
||||
|
||||
```
|
||||
<<<
|
||||
Quote Level 1
|
||||
|
||||
<<<<
|
||||
QuoteLevel 2
|
||||
<<<<
|
||||
|
||||
<<<
|
||||
```
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "quoteblock";
|
||||
exports.types = {block: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /(<<<+)/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var classes = ["tw-quote"];
|
||||
// Get all the details of the match
|
||||
var reEndString = "^" + this.match[1] + "(?!<)";
|
||||
// Move past the <s
|
||||
this.parser.pos = this.matchRegExp.lastIndex;
|
||||
|
||||
// Parse any classes, whitespace and then the optional cite itself
|
||||
classes.push.apply(classes, this.parser.parseClasses());
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var cite = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
|
||||
// before handling the cite, parse the body of the quote
|
||||
var tree= this.parser.parseBlocks(reEndString);
|
||||
// If we got a cite, put it before the text
|
||||
if(cite.length > 0) {
|
||||
tree.unshift({
|
||||
type: "element",
|
||||
tag: "cite",
|
||||
children: cite
|
||||
});
|
||||
}
|
||||
|
||||
// Parse any optional cite
|
||||
this.parser.skipWhitespace({treatNewlinesAsNonWhitespace: true});
|
||||
var cite = this.parser.parseInlineRun(/(\r?\n)/mg);
|
||||
// If we got a cite, push it
|
||||
if(cite.length > 0) {
|
||||
tree.push({
|
||||
type: "element",
|
||||
tag: "cite",
|
||||
children: cite
|
||||
});
|
||||
}
|
||||
|
||||
// Return the blockquote element
|
||||
return [{
|
||||
type: "element",
|
||||
tag: "blockquote",
|
||||
attributes: {
|
||||
class: { type: "string", value: classes.join(" ") },
|
||||
},
|
||||
children: tree
|
||||
}];
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -18,11 +18,11 @@ exports.types = {block: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /^\|(?:[^\n]*)\|(?:[fhck]?)\r?\n/mg;
|
||||
this.matchRegExp = /^\|(?:[^\n]*)\|(?:[fhck]?)\r?(?:\n|$)/mg;
|
||||
};
|
||||
|
||||
var processRow = function(prevColumns) {
|
||||
var cellRegExp = /(?:\|([^\n\|]*)\|)|(\|[fhck]?\r?\n)/mg,
|
||||
var cellRegExp = /(?:\|([^\n\|]*)\|)|(\|[fhck]?\r?(?:\n|$))/mg,
|
||||
cellTermRegExp = /((?:\x20*)\|)/mg,
|
||||
tree = [],
|
||||
col = 0,
|
||||
@@ -38,7 +38,8 @@ var processRow = function(prevColumns) {
|
||||
if(last) {
|
||||
last.rowSpanCount++;
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"rowspan",last.rowSpanCount);
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"valign","center");
|
||||
var vAlign = $tw.utils.getAttributeValueFromParseTreeNode(last.element,"valign","center");
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"valign",vAlign);
|
||||
if(colSpanCount > 1) {
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"colspan",colSpanCount);
|
||||
colSpanCount = 1;
|
||||
@@ -51,9 +52,20 @@ var processRow = function(prevColumns) {
|
||||
colSpanCount++;
|
||||
// Move to just before the `|` terminating the cell
|
||||
this.parser.pos = cellRegExp.lastIndex - 1;
|
||||
} else if(cellMatch[1] === "<" && prevCell) {
|
||||
colSpanCount = 1 + $tw.utils.getAttributeValueFromParseTreeNode(prevCell,"colspan",1);
|
||||
$tw.utils.addAttributeToParseTreeNode(prevCell,"colspan",colSpanCount);
|
||||
colSpanCount = 1;
|
||||
// Move to just before the `|` terminating the cell
|
||||
this.parser.pos = cellRegExp.lastIndex - 1;
|
||||
} else if(cellMatch[2]) {
|
||||
// End of row
|
||||
if(prevCell && colSpanCount > 1) {
|
||||
if(prevCell.attributes && prevCell.attributes && prevCell.attributes.colspan) {
|
||||
colSpanCount += prevCell.attributes.colspan.value;
|
||||
} else {
|
||||
colSpanCount -= 1;
|
||||
}
|
||||
$tw.utils.addAttributeToParseTreeNode(prevCell,"colspan",colSpanCount);
|
||||
}
|
||||
this.parser.pos = cellRegExp.lastIndex - 1;
|
||||
@@ -63,7 +75,16 @@ var processRow = function(prevColumns) {
|
||||
this.parser.pos++;
|
||||
// Look for a space at the start of the cell
|
||||
var spaceLeft = false,
|
||||
chr = this.parser.source.substr(this.parser.pos,1);
|
||||
vAlign = null;
|
||||
if(this.parser.source.substr(this.parser.pos).search(/^\^([^\^]|\^\^)/) === 0) {
|
||||
vAlign = "top";
|
||||
} else if(this.parser.source.substr(this.parser.pos).search(/^,([^,]|,,)/) === 0) {
|
||||
vAlign = "bottom";
|
||||
}
|
||||
if(vAlign) {
|
||||
this.parser.pos++;
|
||||
}
|
||||
var chr = this.parser.source.substr(this.parser.pos,1);
|
||||
while(chr === " ") {
|
||||
spaceLeft = true;
|
||||
this.parser.pos++;
|
||||
@@ -89,7 +110,10 @@ var processRow = function(prevColumns) {
|
||||
// Parse the cell
|
||||
cell.children = this.parser.parseInlineRun(cellTermRegExp,{eatTerminator: true});
|
||||
// Set the alignment for the cell
|
||||
if(cellMatch[1].substr(cellMatch[1].length-1,1) === " ") { // spaceRight
|
||||
if(vAlign) {
|
||||
$tw.utils.addAttributeToParseTreeNode(cell,"valign",vAlign);
|
||||
}
|
||||
if(this.parser.source.substr(this.parser.pos - 2,1) === " ") { // spaceRight
|
||||
$tw.utils.addAttributeToParseTreeNode(cell,"align",spaceLeft ? "center" : "left");
|
||||
} else if(spaceLeft) {
|
||||
$tw.utils.addAttributeToParseTreeNode(cell,"align","right");
|
||||
@@ -107,8 +131,8 @@ var processRow = function(prevColumns) {
|
||||
exports.parse = function() {
|
||||
var rowContainerTypes = {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
|
||||
table = {type: "element", tag: "table", children: []},
|
||||
rowRegExp = /^\|([^\n]*)\|([fhck]?)\r?\n/mg,
|
||||
rowTermRegExp = /(\|(?:[fhck]?)\r?\n)/mg,
|
||||
rowRegExp = /^\|([^\n]*)\|([fhck]?)\r?(?:\n|$)/mg,
|
||||
rowTermRegExp = /(\|(?:[fhck]?)\r?(?:\n|$))/mg,
|
||||
prevColumns = [],
|
||||
currRowType,
|
||||
rowContainer,
|
||||
@@ -124,7 +148,7 @@ exports.parse = function() {
|
||||
this.parser.pos = rowMatch.index + rowMatch[0].length;
|
||||
} else {
|
||||
// Otherwise, create a new row if this one is of a different type
|
||||
if(rowType != currRowType) {
|
||||
if(rowType !== currRowType) {
|
||||
rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: []};
|
||||
table.children.push(rowContainer);
|
||||
currRowType = rowType;
|
||||
|
||||
@@ -40,7 +40,7 @@ exports.init = function(parser) {
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
var reEnd = /\r?\n\$\$\$\r?\n/mg;
|
||||
var reEnd = /\r?\n\$\$\$\r?(?:\n|$)/mg;
|
||||
// Save the type
|
||||
var parseType = this.match[1],
|
||||
renderType = this.match[2];
|
||||
@@ -66,7 +66,7 @@ exports.parse = function() {
|
||||
} else {
|
||||
// Otherwise, render to the rendertype and return in a <PRE> tag
|
||||
var widgetNode = this.parser.wiki.makeWidget(parser),
|
||||
container = $tw.document.createElement("div");
|
||||
container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
var text = renderType === "text/html" ? container.innerHTML : container.textContent;
|
||||
return [{
|
||||
|
||||
@@ -28,7 +28,7 @@ DownloadSaver.prototype.save = function(text,method,callback) {
|
||||
// Set up the link
|
||||
var link = document.createElement("a");
|
||||
link.setAttribute("target","_blank");
|
||||
if(Blob != undefined) {
|
||||
if(Blob !== undefined) {
|
||||
var blob = new Blob([text], {type: "text/html"});
|
||||
link.setAttribute("href", URL.createObjectURL(blob));
|
||||
} else {
|
||||
|
||||
75
core/modules/savers/fsosaver.js
Normal file
75
core/modules/savers/fsosaver.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/fsosaver.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Handles saving changes via MS FileSystemObject ActiveXObject
|
||||
|
||||
Note: Since TiddlyWiki's markup contains the MOTW, the FileSystemObject normally won't be available.
|
||||
However, if the wiki is loaded as an .HTA file (Windows HTML Applications) then the FSO can be used.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var FSOSaver = function(wiki) {
|
||||
};
|
||||
|
||||
FSOSaver.prototype.save = function(text,method,callback) {
|
||||
// Bail out unless this is a save (rather than a download)
|
||||
if(method !== "save") {
|
||||
return false;
|
||||
}
|
||||
// Get the pathname of this document
|
||||
var pathname = unescape(document.location.pathname);
|
||||
// Test for a Windows path of the form /x:\blah...
|
||||
if(/^\/[A-Z]\:\\[^\\]+/i.test(pathname)) { // ie: ^/[a-z]:/[^/]+
|
||||
// Remove the leading slash
|
||||
pathname = pathname.substr(1);
|
||||
} else if(document.location.hostname !== "" && /^\/\\[^\\]+\\[^\\]+/i.test(pathname)) { // test for \\server\share\blah... - ^/[^/]+/[^/]+
|
||||
// Remove the leading slash
|
||||
pathname = pathname.substr(1);
|
||||
// reconstruct UNC path
|
||||
pathname = "\\\\" + document.location.hostname + pathname;
|
||||
} else return false;
|
||||
|
||||
// Save the file (as UTF-16)
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var file = fso.OpenTextFile(pathname,2,-1,-1);
|
||||
|
||||
file.Write(text);
|
||||
file.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
FSOSaver.prototype.info = {
|
||||
name: "FSOSaver",
|
||||
priority: 120
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
try {
|
||||
return (window.location.protocol === "file:") && !!(new ActiveXObject("Scripting.FileSystemObject"));
|
||||
} catch(e) { return false; }
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new FSOSaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
73
core/modules/savers/tiddlyie.js
Normal file
73
core/modules/savers/tiddlyie.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/tiddlyie.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Handles saving changes via Internet Explorer BHO extenion (TiddlyIE)
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var TiddlyIESaver = function(wiki) {
|
||||
};
|
||||
|
||||
TiddlyIESaver.prototype.save = function(text,method,callback) {
|
||||
// Bail out unless this is a save (rather than a download)
|
||||
if(method !== "save") {
|
||||
return false;
|
||||
}
|
||||
// check existence of TiddlyIE BHO extension (note: only works after document is complete)
|
||||
if(typeof(window.TiddlyIE) != "undefined") {
|
||||
// Get the pathname of this document
|
||||
var pathname = unescape(document.location.pathname);
|
||||
// Test for a Windows path of the form /x:/blah...
|
||||
if(/^\/[A-Z]\:\/[^\/]+/i.test(pathname)) { // ie: ^/[a-z]:/[^/]+ (is this better?: ^/[a-z]:/[^/]+(/[^/]+)*\.[^/]+ )
|
||||
// Remove the leading slash
|
||||
pathname = pathname.substr(1);
|
||||
// Convert slashes to backslashes
|
||||
pathname = pathname.replace(/\//g,"\\");
|
||||
} else if(document.hostname !== "" && /^\/[^\/]+\/[^\/]+/i.test(pathname)) { // test for \\server\share\blah... - ^/[^/]+/[^/]+
|
||||
// Convert slashes to backslashes
|
||||
pathname = pathname.replace(/\//g,"\\");
|
||||
// reconstruct UNC path
|
||||
pathname = "\\\\" + document.location.hostname + pathname;
|
||||
} else return false;
|
||||
|
||||
// Prompt the user to save the file
|
||||
window.TiddlyIE.save(pathname, text);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
TiddlyIESaver.prototype.info = {
|
||||
name: "tiddlyiesaver",
|
||||
priority: 1500
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
return (window.location.protocol === "file:");
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new TiddlyIESaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -27,10 +27,11 @@ UploadSaver.prototype.save = function(text,method,callback) {
|
||||
return false;
|
||||
}
|
||||
// Get the various parameters we need
|
||||
var backupDir = ".",
|
||||
var backupDir = this.wiki.getTextReference("$:/UploadBackupDir") || ".",
|
||||
username = this.wiki.getTextReference("$:/UploadName"),
|
||||
password = $tw.utils.getPassword("upload"),
|
||||
uploadDir = ".",
|
||||
uploadDir = this.wiki.getTextReference("$:/UploadDir") || ".",
|
||||
uploadFilename = this.wiki.getTextReference("$:/UploadFilename") || "index.html",
|
||||
url = this.wiki.getTextReference("$:/UploadURL");
|
||||
// Bail out if we don't have the bits we need
|
||||
if(!username || username.toString().trim() === "" || !password || password.toString().trim() === "") {
|
||||
@@ -47,7 +48,7 @@ UploadSaver.prototype.save = function(text,method,callback) {
|
||||
head.push("--" + boundary + "\r\nContent-disposition: form-data; name=\"UploadPlugin\"\r\n");
|
||||
head.push("backupDir=" + backupDir + ";user=" + username + ";password=" + password + ";uploaddir=" + uploadDir + ";;");
|
||||
head.push("\r\n" + "--" + boundary);
|
||||
head.push("Content-disposition: form-data; name=\"userfile\"; filename=\"index.html\"");
|
||||
head.push("Content-disposition: form-data; name=\"userfile\"; filename=\"" + uploadFilename + "\"");
|
||||
head.push("Content-Type: text/html;charset=UTF-8");
|
||||
head.push("Content-Length: " + text.length + "\r\n");
|
||||
head.push("");
|
||||
@@ -60,7 +61,7 @@ UploadSaver.prototype.save = function(text,method,callback) {
|
||||
http.setRequestHeader("Content-Type","multipart/form-data; ;charset=UTF-8; boundary=" + boundary);
|
||||
http.onreadystatechange = function() {
|
||||
if(http.readyState == 4 && http.status == 200) {
|
||||
if(http.responseText.trim() === "0 - Fileindex.html") {
|
||||
if(http.responseText.substr(0,4) === "0 - ") {
|
||||
callback(null);
|
||||
} else {
|
||||
callback(http.responseText);
|
||||
@@ -77,7 +78,7 @@ Information about this saver
|
||||
*/
|
||||
UploadSaver.prototype.info = {
|
||||
name: "upload",
|
||||
priority: 500
|
||||
priority: 2000
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,10 +16,13 @@ var widget = require("$:/core/modules/widgets/widget.js");
|
||||
|
||||
exports.startup = function() {
|
||||
var modules,n,m,f,commander;
|
||||
// Load modules
|
||||
// Load utility modules and initialise the logger
|
||||
$tw.modules.applyMethods("utils",$tw.utils);
|
||||
$tw.logger = new $tw.utils.Logger();
|
||||
$tw.log = $tw.logger.log;
|
||||
// Load other modules
|
||||
$tw.modules.applyMethods("global",$tw);
|
||||
$tw.modules.applyMethods("config",$tw.config);
|
||||
$tw.modules.applyMethods("utils",$tw.utils);
|
||||
if($tw.browser) {
|
||||
$tw.utils.getBrowserInfo($tw.browser);
|
||||
}
|
||||
@@ -59,13 +62,14 @@ exports.startup = function() {
|
||||
});
|
||||
// Install the animator
|
||||
$tw.anim = new $tw.utils.Animator();
|
||||
// Kick off the stylesheet manager
|
||||
$tw.stylesheetManager = new $tw.utils.StylesheetManager($tw.wiki);
|
||||
// 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: document
|
||||
});
|
||||
$tw.rootWidget = new widget.widget({
|
||||
type: "widget",
|
||||
children: []
|
||||
},{
|
||||
wiki: $tw.wiki,
|
||||
document: document
|
||||
});
|
||||
// Install the modal message mechanism
|
||||
$tw.modal = new $tw.utils.Modal($tw.wiki);
|
||||
$tw.rootWidget.addEventListener("tw-modal",function(event) {
|
||||
@@ -102,8 +106,11 @@ exports.startup = function() {
|
||||
serviceName: "Set a new password for this TiddlyWiki",
|
||||
noUserName: true,
|
||||
submitText: "Set password",
|
||||
canCancel: true,
|
||||
callback: function(data) {
|
||||
$tw.crypto.setPassword(data.password);
|
||||
if(data) {
|
||||
$tw.crypto.setPassword(data.password);
|
||||
}
|
||||
return true; // Get rid of the password prompt
|
||||
}
|
||||
});
|
||||
@@ -111,6 +118,35 @@ exports.startup = function() {
|
||||
$tw.rootWidget.addEventListener("tw-clear-password",function(event) {
|
||||
$tw.crypto.setPassword(null);
|
||||
});
|
||||
// Set up the favicon
|
||||
var faviconTitle = "$:/favicon.ico",
|
||||
faviconLink = document.getElementById("faviconLink"),
|
||||
setFavicon = function() {
|
||||
var tiddler = $tw.wiki.getTiddler(faviconTitle);
|
||||
if(tiddler) {
|
||||
faviconLink.setAttribute("href","data:" + tiddler.fields.type + ";base64," + tiddler.fields.text);
|
||||
}
|
||||
};
|
||||
setFavicon();
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
if($tw.utils.hop(changes,faviconTitle)) {
|
||||
setFavicon();
|
||||
}
|
||||
});
|
||||
// Set up the styles
|
||||
var styleTemplateTitle = "$:/core/ui/PageStylesheet",
|
||||
styleParser = $tw.wiki.parseTiddler(styleTemplateTitle);
|
||||
$tw.styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: $tw.fakeDocument});
|
||||
$tw.styleContainer = $tw.fakeDocument.createElement("style");
|
||||
$tw.styleWidgetNode.render($tw.styleContainer,null);
|
||||
$tw.styleElement = document.createElement("style");
|
||||
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
|
||||
document.head.insertBefore($tw.styleElement,document.head.firstChild);
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
|
||||
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
|
||||
}
|
||||
});
|
||||
// Display the PageMacros, which includes the PageTemplate
|
||||
var templateTitle = "$:/core/ui/PageMacros",
|
||||
parser = $tw.wiki.parseTiddler(templateTitle);
|
||||
@@ -122,6 +158,9 @@ exports.startup = function() {
|
||||
$tw.wiki.addEventListener("change",function(changes) {
|
||||
$tw.pageWidgetNode.refresh(changes,$tw.pageContainer,null);
|
||||
});
|
||||
// Fix up the link between the root widget and the page container
|
||||
$tw.rootWidget.domNodes = [$tw.pageContainer];
|
||||
$tw.rootWidget.children = [$tw.pageWidgetNode];
|
||||
// If we're being viewed on a data: URI then give instructions for how to save
|
||||
if(document.location.protocol === "data:") {
|
||||
$tw.utils.dispatchCustomEvent(document,"tw-modal",{
|
||||
|
||||
@@ -19,6 +19,8 @@ wiki: wiki to be synced
|
||||
function Syncer(options) {
|
||||
var self = this;
|
||||
this.wiki = options.wiki;
|
||||
// Make a logger
|
||||
this.log = $tw.logger.makeLog("syncer");
|
||||
// Find a working syncadaptor
|
||||
this.syncadaptor = undefined;
|
||||
$tw.modules.forEachModuleOfType("syncadaptor",function(title,module) {
|
||||
@@ -36,18 +38,7 @@ function Syncer(options) {
|
||||
Error handling
|
||||
*/
|
||||
Syncer.prototype.showError = function(error) {
|
||||
alert("Syncer error: " + error);
|
||||
$tw.utils.log("Syncer error: " + error);
|
||||
};
|
||||
|
||||
/*
|
||||
Message logging
|
||||
*/
|
||||
Syncer.prototype.log = function(/* arguments */) {
|
||||
var args = Array.prototype.slice.call(arguments,0);
|
||||
args[0] = "Syncer: " + args[0];
|
||||
// Temporarily disable logging to help the wood vs. trees situation; we need better filtering of log messages
|
||||
//$tw.utils.log.apply(null,args);
|
||||
this.log("Error: " + error);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -68,13 +59,11 @@ Syncer.prototype.init = function() {
|
||||
// Hashmap by title of {revision:,changeCount:,adaptorInfo:}
|
||||
this.tiddlerInfo = {};
|
||||
// Record information for known tiddlers
|
||||
this.wiki.forEachTiddler(function(title,tiddler) {
|
||||
if(tiddler.fields["revision"]) {
|
||||
self.tiddlerInfo[title] = {
|
||||
revision: tiddler.fields["revision"],
|
||||
adaptorInfo: self.syncadaptor.getTiddlerInfo(tiddler),
|
||||
changeCount: self.wiki.getChangeCount(title)
|
||||
}
|
||||
this.wiki.forEachTiddler({includeSystem: true},function(title,tiddler) {
|
||||
self.tiddlerInfo[title] = {
|
||||
revision: tiddler.fields["revision"],
|
||||
adaptorInfo: self.syncadaptor.getTiddlerInfo(tiddler),
|
||||
changeCount: self.wiki.getChangeCount(title)
|
||||
}
|
||||
});
|
||||
// Tasks are {type: "load"/"save"/"delete", title:, queueTime:, lastModificationTime:}
|
||||
@@ -385,6 +374,9 @@ Syncer.prototype.processTaskQueue = function() {
|
||||
this.taskInProgress[task.title] = task;
|
||||
// Dispatch the task
|
||||
this.dispatchTask(task,function(err) {
|
||||
if(err) {
|
||||
self.showError("Sync error while processing '" + task.title + "':\n" + err);
|
||||
}
|
||||
// Mark that this task is no longer in progress
|
||||
delete self.taskInProgress[task.title];
|
||||
// Process the next task
|
||||
@@ -436,19 +428,21 @@ Syncer.prototype.dispatchTask = function(task,callback) {
|
||||
var changeCount = this.wiki.getChangeCount(task.title),
|
||||
tiddler = this.wiki.getTiddler(task.title);
|
||||
this.log("Dispatching 'save' task:",task.title);
|
||||
this.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
// Adjust the info stored about this tiddler
|
||||
self.tiddlerInfo[task.title] = {
|
||||
changeCount: changeCount,
|
||||
adaptorInfo: adaptorInfo,
|
||||
revision: revision
|
||||
};
|
||||
// Invoke the callback
|
||||
callback(null);
|
||||
});
|
||||
if(tiddler) {
|
||||
this.syncadaptor.saveTiddler(tiddler,function(err,adaptorInfo,revision) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
// Adjust the info stored about this tiddler
|
||||
self.tiddlerInfo[task.title] = {
|
||||
changeCount: changeCount,
|
||||
adaptorInfo: adaptorInfo,
|
||||
revision: revision
|
||||
};
|
||||
// Invoke the callback
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
} else if(task.type === "load") {
|
||||
// Load the tiddler
|
||||
this.log("Dispatching 'load' task:",task.title);
|
||||
@@ -457,7 +451,9 @@ Syncer.prototype.dispatchTask = function(task,callback) {
|
||||
return callback(err);
|
||||
}
|
||||
// Store the tiddler
|
||||
self.storeTiddler(tiddlerFields);
|
||||
if(tiddlerFields) {
|
||||
self.storeTiddler(tiddlerFields);
|
||||
}
|
||||
// Invoke the callback
|
||||
callback(null);
|
||||
});
|
||||
|
||||
@@ -13,7 +13,10 @@ Manages themes and styling.
|
||||
"use strict";
|
||||
|
||||
var THEME_PLUGIN_TITLE = "$:/theme", // This tiddler contains the title of the current theme plugin
|
||||
DEFAULT_THEME_PLUGIN = "$:/themes/tiddlywiki/vanilla";
|
||||
DEFAULT_THEME_PLUGINS = [
|
||||
"$:/themes/tiddlywiki/snowwhite",
|
||||
"$:/themes/tiddlywiki/vanilla"
|
||||
];
|
||||
|
||||
function ThemeManager(wiki) {
|
||||
this.wiki = wiki;
|
||||
@@ -32,7 +35,12 @@ function ThemeManager(wiki) {
|
||||
|
||||
ThemeManager.prototype.switchTheme = function() {
|
||||
// Get the name of the current theme
|
||||
var themePluginTitle = this.wiki.getTiddlerText(THEME_PLUGIN_TITLE,DEFAULT_THEME_PLUGIN);
|
||||
var themePluginTitle = this.wiki.getTiddlerText(THEME_PLUGIN_TITLE);
|
||||
// If it doesn't exist, then fallback to one of the default themes
|
||||
var index = 0;
|
||||
while(!this.wiki.getTiddler(themePluginTitle) && index < DEFAULT_THEME_PLUGINS.length) {
|
||||
themePluginTitle = DEFAULT_THEME_PLUGINS[index++];
|
||||
}
|
||||
// Accumulate the titles of the plugins that we need to load
|
||||
var themePlugins = [],
|
||||
self = this,
|
||||
@@ -40,8 +48,9 @@ ThemeManager.prototype.switchTheme = function() {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
if(tiddler && tiddler.isPlugin() && themePlugins.indexOf(title) === -1) {
|
||||
themePlugins.push(title);
|
||||
var pluginInfo = JSON.parse(self.wiki.getTiddlerText(title));
|
||||
$tw.utils.each(pluginInfo.dependents,function(title) {
|
||||
var pluginInfo = JSON.parse(self.wiki.getTiddlerText(title)),
|
||||
dependents = $tw.utils.parseStringArray(tiddler.fields.dependents || "");
|
||||
$tw.utils.each(dependents,function(title) {
|
||||
accumulatePlugin(title);
|
||||
});
|
||||
}
|
||||
|
||||
81
core/modules/utils/crypto.js
Normal file
81
core/modules/utils/crypto.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/crypto.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
Utility functions related to crypto.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Look for an encrypted store area in the text of a TiddlyWiki file
|
||||
*/
|
||||
exports.extractEncryptedStoreArea = function(text) {
|
||||
var encryptedStoreAreaStartMarker = "<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">",
|
||||
encryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker);
|
||||
if(encryptedStoreAreaStart !== -1) {
|
||||
var encryptedStoreAreaEnd = text.indexOf("</pre>",encryptedStoreAreaStart);
|
||||
if(encryptedStoreAreaEnd !== -1) {
|
||||
return $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
Attempt to extract the tiddlers from an encrypted store area using the current password. If the password is not provided then the password in the password store will be used
|
||||
*/
|
||||
exports.decryptStoreArea = function(encryptedStoreArea,password) {
|
||||
var decryptedText = $tw.crypto.decrypt(encryptedStoreArea,password);
|
||||
if(decryptedText) {
|
||||
var json = JSON.parse(decryptedText),
|
||||
tiddlers = [];
|
||||
for(var title in json) {
|
||||
if(title !== "$:/isEncrypted") {
|
||||
tiddlers.push(json[title]);
|
||||
}
|
||||
}
|
||||
return tiddlers;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
exports.decryptStoreAreaInteractive = function(encryptedStoreArea,callback) {
|
||||
// Try to decrypt with the current password
|
||||
var tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);
|
||||
if(tiddlers) {
|
||||
callback(tiddlers);
|
||||
} else {
|
||||
// Prompt for a new password and keep trying
|
||||
$tw.passwordPrompt.createPrompt({
|
||||
serviceName: "Enter a password to decrypt the imported TiddlyWiki",
|
||||
noUserName: true,
|
||||
canCancel: true,
|
||||
submitText: "Decrypt",
|
||||
callback: function(data) {
|
||||
// Exit if the user cancelled
|
||||
if(!data) {
|
||||
return false;
|
||||
}
|
||||
// Attempt to decrypt the tiddlers
|
||||
var tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea,data.password);
|
||||
if(tiddlers) {
|
||||
callback(tiddlers);
|
||||
// Exit and remove the password prompt
|
||||
return true;
|
||||
} else {
|
||||
// We didn't decrypt everything, so continue to prompt for password
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -18,9 +18,11 @@ Set style properties of an element
|
||||
styles: ordered array of {name: value} pairs
|
||||
*/
|
||||
exports.setStyle = function(element,styles) {
|
||||
for(var t=0; t<styles.length; t++) {
|
||||
for(var styleName in styles[t]) {
|
||||
element.style[$tw.utils.convertStyleNameToPropertyName(styleName)] = styles[t][styleName];
|
||||
if(element.nodeType === 1) { // Element.ELEMENT_NODE
|
||||
for(var t=0; t<styles.length; t++) {
|
||||
for(var styleName in styles[t]) {
|
||||
element.style[$tw.utils.convertStyleNameToPropertyName(styleName)] = styles[t][styleName];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -130,15 +132,7 @@ exports.convertEventName = function(eventName) {
|
||||
|
||||
// Setup constants for the current browser
|
||||
exports.getBrowserInfo = function(info) {
|
||||
info.requestFullScreen = document.body.webkitRequestFullScreen !== undefined ? "webkitRequestFullScreen" :
|
||||
document.body.mozRequestFullScreen !== undefined ? "mozRequestFullScreen" :
|
||||
document.body.requestFullScreen !== undefined ? "requestFullScreen" : "";
|
||||
info.cancelFullScreen = document.webkitCancelFullScreen !== undefined ? "webkitCancelFullScreen" :
|
||||
document.mozCancelFullScreen !== undefined ? "mozCancelFullScreen" :
|
||||
document.cancelFullScreen !== undefined ? "cancelFullScreen" : "";
|
||||
info.isFullScreen = document.webkitIsFullScreen !== undefined ? "webkitIsFullScreen" :
|
||||
document.mozFullScreen !== undefined ? "mozFullScreen" :
|
||||
document.fullScreen !== undefined ? "fullScreen" : "";
|
||||
info.isIE = (/msie|trident/i.test(navigator.userAgent));
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -18,7 +18,7 @@ Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
|
||||
*/
|
||||
exports.domContains = function(a,b) {
|
||||
return a.contains ?
|
||||
a != b && a.contains(b) :
|
||||
a !== b && a.contains(b) :
|
||||
!!(a.compareDocumentPosition(b) & 16);
|
||||
};
|
||||
|
||||
|
||||
@@ -67,13 +67,12 @@ Notifier.prototype.display = function(title,options) {
|
||||
{opacity: "0.0"},
|
||||
{transform: "translateX(" + (notification.offsetWidth) + "px)"}
|
||||
]);
|
||||
// Set up an event for the transition end
|
||||
notification.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
|
||||
// Remove the modal message from the DOM once the transition ends
|
||||
setTimeout(function() {
|
||||
if(notification.parentNode) {
|
||||
// Remove the modal message from the DOM
|
||||
document.body.removeChild(notification);
|
||||
}
|
||||
},false);
|
||||
},duration);
|
||||
},$tw.config.preferences.notificationDuration);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/styles.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
The stylesheet manager automatically renders any tiddlers tagged "$:/tags/stylesheet" as HTML style elements.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var STYLESHEET_ID_PREFIX = "tw-tiddler-stylesheet-",
|
||||
STYLESHEET_TAG = "$:/tags/stylesheet";
|
||||
|
||||
function StylesheetManager(wiki) {
|
||||
this.wiki = wiki;
|
||||
this.stylesheets = {}; // Hashmap of currently rendered stylesheets
|
||||
// Apply initial stylesheets
|
||||
var self = this,
|
||||
stylesheetTiddlers = this.wiki.filterTiddlers("[is[shadow]!has[draft.of]tag[" + STYLESHEET_TAG + "]] [!is[shadow]!has[draft.of]tag[" + STYLESHEET_TAG + "]]");
|
||||
$tw.utils.each(stylesheetTiddlers,function(title,index) {
|
||||
self.addStylesheet(title);
|
||||
});
|
||||
// Listen out for changes
|
||||
this.wiki.addEventListener("change",function(changes) {
|
||||
self.handleTiddlerChanges(changes);
|
||||
});
|
||||
}
|
||||
|
||||
StylesheetManager.prototype.addStylesheet = function(title) {
|
||||
// Record the stylesheet in the hashmap
|
||||
this.stylesheets[title] = true;
|
||||
// Parse the tiddler and render as plain text
|
||||
var text = this.wiki.renderTiddler("text/plain",title);
|
||||
// Create a style element and put it in the document
|
||||
var styleNode = document.createElement("style");
|
||||
styleNode.setAttribute("type","text/css");
|
||||
styleNode.setAttribute("id",STYLESHEET_ID_PREFIX + title);
|
||||
styleNode.appendChild(document.createTextNode(text));
|
||||
document.getElementsByTagName("head")[0].appendChild(styleNode);
|
||||
};
|
||||
|
||||
StylesheetManager.prototype.removeStylesheet = function(title) {
|
||||
// Remove the stylesheet from the hashmap
|
||||
if($tw.utils.hop(this.stylesheets,title)) {
|
||||
delete this.stylesheets[title];
|
||||
}
|
||||
// Remove the stylesheet from the document
|
||||
var styleNode = document.getElementById(STYLESHEET_ID_PREFIX + title);
|
||||
if(styleNode) {
|
||||
styleNode.parentNode.removeChild(styleNode);
|
||||
}
|
||||
};
|
||||
|
||||
StylesheetManager.prototype.handleTiddlerChanges = function(changes) {
|
||||
var self = this;
|
||||
$tw.utils.each(changes,function(change,title) {
|
||||
// Remove any existing stylesheet for the changed tiddler
|
||||
if($tw.utils.hop(self.stylesheets,title)) {
|
||||
self.removeStylesheet(title);
|
||||
}
|
||||
// Add the stylesheet if it is tagged and not a draft
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
if(tiddler && tiddler.hasTag(STYLESHEET_TAG) && !tiddler.hasField("draft.of")) {
|
||||
self.addStylesheet(title);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.StylesheetManager = StylesheetManager;
|
||||
|
||||
})();
|
||||
@@ -66,6 +66,7 @@ TW_Element.prototype.insertBefore = function(node,nextSibling) {
|
||||
var p = this.children.indexOf(nextSibling);
|
||||
if(p !== -1) {
|
||||
this.children.splice(p,0,node);
|
||||
node.parentNode = this;
|
||||
} else {
|
||||
this.appendChild(node);
|
||||
}
|
||||
@@ -181,6 +182,6 @@ var document = {
|
||||
},
|
||||
};
|
||||
|
||||
exports.document = document;
|
||||
exports.fakeDocument = document;
|
||||
|
||||
})();
|
||||
|
||||
43
core/modules/utils/logger.js
Normal file
43
core/modules/utils/logger.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*\
|
||||
title: $:/core/modules/utils/logger.js
|
||||
type: application/javascript
|
||||
module-type: utils
|
||||
|
||||
A basic logging implementation
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Make a new logger
|
||||
*/
|
||||
function Logger() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Make a log function for a particular component
|
||||
*/
|
||||
Logger.prototype.makeLog = function(componentName) {
|
||||
var self = this;
|
||||
return function(/* args */) {
|
||||
self.log.apply(self.log,[componentName + ":"].concat(Array.prototype.slice.call(arguments,0)));
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
Log a message
|
||||
*/
|
||||
Logger.prototype.log = function(/* args */) {
|
||||
if(console !== undefined && console.log !== undefined) {
|
||||
return Function.apply.call(console.log, console, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
exports.Logger = Logger;
|
||||
|
||||
})();
|
||||
@@ -19,6 +19,13 @@ exports.addAttributeToParseTreeNode = function(node,name,value) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.getAttributeValueFromParseTreeNode = function(node,name,defaultValue) {
|
||||
if(node.type === "element" && node.attributes && node.attributes[name] && node.attributes[name].value !== undefined) {
|
||||
return node.attributes[name].value;
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
exports.addClassToParseTreeNode = function(node,classString) {
|
||||
var classes = [];
|
||||
if(node.type === "element") {
|
||||
|
||||
@@ -275,7 +275,7 @@ exports.unescapeLineBreaks = function(s) {
|
||||
// Copied from peg.js, thanks to David Majda
|
||||
exports.escape = function(ch) {
|
||||
var charCode = ch.charCodeAt(0);
|
||||
if (charCode <= 0xFF) {
|
||||
if(charCode <= 0xFF) {
|
||||
return '\\x' + $tw.utils.pad(charCode.toString(16).toUpperCase());
|
||||
} else {
|
||||
return '\\u' + $tw.utils.pad(charCode.toString(16).toUpperCase(),4);
|
||||
|
||||
@@ -39,8 +39,8 @@ BrowseWidget.prototype.render = function(parent,nextSibling) {
|
||||
domNode.setAttribute("multiple","multiple");
|
||||
// Add a click event handler
|
||||
domNode.addEventListener("change",function (event) {
|
||||
self.wiki.readFiles(event.target.files,function(tiddlerFields) {
|
||||
self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])});
|
||||
self.wiki.readFiles(event.target.files,function(tiddlerFieldsArray) {
|
||||
self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
|
||||
});
|
||||
return false;
|
||||
},false);
|
||||
|
||||
64
core/modules/widgets/codeblock.js
Normal file
64
core/modules/widgets/codeblock.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/codeblock.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Code block node widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var CodeBlockWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
CodeBlockWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
CodeBlockWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
var codeNode = this.document.createElement("code");
|
||||
if(this.getAttribute("language")) {
|
||||
codeNode.setAttribute("class",this.getAttribute("language"));
|
||||
}
|
||||
var domNode = this.document.createElement("pre");
|
||||
codeNode.appendChild(this.document.createTextNode(this.getAttribute("code")));
|
||||
domNode.appendChild(codeNode);
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.domNodes.push(domNode);
|
||||
|
||||
if(this.postRender) {
|
||||
this.postRender();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
CodeBlockWidget.prototype.execute = function() {
|
||||
// Nothing to do for a text node
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
CodeBlockWidget.prototype.refresh = function(changedTiddlers) {
|
||||
return false;
|
||||
};
|
||||
|
||||
exports.codeblock = CodeBlockWidget;
|
||||
|
||||
})();
|
||||
@@ -87,12 +87,14 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||
this.dragEnterCount = 0;
|
||||
// Remove highlighting
|
||||
$tw.utils.removeClass(this.domNodes[0],"tw-dragover");
|
||||
// Try to import the various data types we understand
|
||||
this.importData(dataTransfer);
|
||||
// Import any files in the drop
|
||||
this.wiki.readFiles(dataTransfer.files,function(tiddlerFields) {
|
||||
self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])});
|
||||
var numFiles = this.wiki.readFiles(dataTransfer.files,function(tiddlerFieldsArray) {
|
||||
self.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify(tiddlerFieldsArray)});
|
||||
});
|
||||
// Try to import the various data types we understand
|
||||
if(numFiles === 0) {
|
||||
this.importData(dataTransfer);
|
||||
}
|
||||
// Tell the browser that we handled the drop
|
||||
event.preventDefault();
|
||||
// Stop the drop ripple up to any parent handlers
|
||||
@@ -100,30 +102,62 @@ DropZoneWidget.prototype.handleDropEvent = function(event) {
|
||||
};
|
||||
|
||||
DropZoneWidget.prototype.importData = function(dataTransfer) {
|
||||
// Try each provided data type in turn
|
||||
for(var t=0; t<this.importDataTypes.length; t++) {
|
||||
var dataType = this.importDataTypes[t];
|
||||
var data = dataTransfer.getData(dataType.type);
|
||||
if(data !== "") {
|
||||
var tiddlerFields = dataType.convertToFields(data);
|
||||
if(!tiddlerFields.title) {
|
||||
tiddlerFields.title = this.wiki.generateNewTitle("Untitled");
|
||||
if(!$tw.browser.isIE || this.importDataTypes[t].IECompatible) {
|
||||
// Get the data
|
||||
var dataType = this.importDataTypes[t];
|
||||
var data = dataTransfer.getData(dataType.type);
|
||||
// Import the tiddlers in the data
|
||||
if(data !== "" && data !== null) {
|
||||
var tiddlerFields = dataType.convertToFields(data);
|
||||
if(!tiddlerFields.title) {
|
||||
tiddlerFields.title = this.wiki.generateNewTitle("Untitled");
|
||||
}
|
||||
this.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])});
|
||||
return;
|
||||
}
|
||||
this.dispatchEvent({type: "tw-import-tiddlers", param: JSON.stringify([tiddlerFields])});
|
||||
return;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
DropZoneWidget.prototype.importDataTypes = [
|
||||
{type: "text/vnd.tiddler", convertToFields: function(data) {
|
||||
{type: "text/vnd.tiddler", IECompatible: false, convertToFields: function(data) {
|
||||
return JSON.parse(data);
|
||||
}},
|
||||
{type: "text/plain", convertToFields: function(data) {
|
||||
{type: "URL", IECompatible: true, convertToFields: function(data) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURI(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return JSON.parse(match[1]);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/x-moz-url", IECompatible: false, convertToFields: function(data) {
|
||||
// Check for tiddler data URI
|
||||
var match = decodeURI(data).match(/^data\:text\/vnd\.tiddler,(.*)/i);
|
||||
if(match) {
|
||||
return JSON.parse(match[1]);
|
||||
} else {
|
||||
return { // As URL string
|
||||
text: data
|
||||
};
|
||||
}
|
||||
}},
|
||||
{type: "text/plain", IECompatible: false, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/uri-list", convertToFields: function(data) {
|
||||
{type: "Text", IECompatible: true, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
}},
|
||||
{type: "text/uri-list", IECompatible: false, convertToFields: function(data) {
|
||||
return {
|
||||
text: data
|
||||
};
|
||||
|
||||
@@ -37,17 +37,19 @@ EditTextWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Execute our logic
|
||||
this.execute();
|
||||
// Create our element
|
||||
var editInfo = this.getEditInfo();
|
||||
var domNode = this.document.createElement(this.editTag);
|
||||
if(this.editType) {
|
||||
domNode.setAttribute("type",this.editType);
|
||||
}
|
||||
if(this.editPlaceholder) {
|
||||
if(editInfo.value === "" && this.editPlaceholder) {
|
||||
domNode.setAttribute("placeholder",this.editPlaceholder);
|
||||
}
|
||||
// Assign classes
|
||||
domNode.className = this.editClass;
|
||||
if(this.editClass) {
|
||||
domNode.className = this.editClass;
|
||||
}
|
||||
// Set the text
|
||||
var editInfo = this.getEditInfo();
|
||||
if(this.editTag === "textarea") {
|
||||
domNode.appendChild(this.document.createTextNode(editInfo.value));
|
||||
} else {
|
||||
|
||||
@@ -33,16 +33,8 @@ EditWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.renderChildren(parent,nextSibling);
|
||||
};
|
||||
|
||||
// Mappings from content type to editor type
|
||||
// TODO: This information should be configurable/extensible
|
||||
var editorTypeMappings = {
|
||||
"text/vnd.tiddlywiki": "text",
|
||||
"image/svg+xml": "text",
|
||||
"image/jpg": "bitmap",
|
||||
"image/jpeg": "bitmap",
|
||||
"image/gif": "bitmap",
|
||||
"image/png": "bitmap"
|
||||
};
|
||||
// Mappings from content type to editor type are stored in tiddlers with this prefix
|
||||
var EDITOR_MAPPING_PREFIX = "$:/config/EditorTypeMappings/";
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
@@ -53,6 +45,7 @@ EditWidget.prototype.execute = function() {
|
||||
this.editField = this.getAttribute("field","text");
|
||||
this.editIndex = this.getAttribute("index");
|
||||
this.editClass = this.getAttribute("class");
|
||||
this.editPlaceholder = this.getAttribute("placeholder");
|
||||
// Get the content type of the thing we're editing
|
||||
var type;
|
||||
if(this.editField === "text") {
|
||||
@@ -63,15 +56,16 @@ EditWidget.prototype.execute = function() {
|
||||
}
|
||||
type = type || "text/vnd.tiddlywiki";
|
||||
// Choose the appropriate edit widget
|
||||
var editorType = editorTypeMappings[type] || "text";
|
||||
var editorType = this.wiki.getTiddlerText(EDITOR_MAPPING_PREFIX + type) || "text";
|
||||
// Make the child widgets
|
||||
this.makeChildWidgets([{
|
||||
type: "edit-" + editorType,
|
||||
attributes: {
|
||||
title: {type: "string", value: this.editTitle},
|
||||
tiddler: {type: "string", value: this.editTitle},
|
||||
field: {type: "string", value: this.editField},
|
||||
index: {type: "string", value: this.editIndex},
|
||||
"class": {type: "string", value: this.editClass}
|
||||
"class": {type: "string", value: this.editClass},
|
||||
"placeholder": {type: "string", value: this.editPlaceholder}
|
||||
}
|
||||
}]);
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
||||
if(tiddler && typeof event.param === "string") {
|
||||
var name = event.param.toLowerCase();
|
||||
if(name !== "" && !$tw.utils.hop(tiddler.fields,name)) {
|
||||
var addition = {};
|
||||
var addition = this.wiki.getModificationFields();
|
||||
addition[name] = "";
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
||||
}
|
||||
@@ -88,9 +88,12 @@ FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
|
||||
if(tiddler && tiddler.fields.tags) {
|
||||
var p = tiddler.fields.tags.indexOf(event.param);
|
||||
if(p !== -1) {
|
||||
var modification = {};
|
||||
var modification = this.wiki.getModificationFields();
|
||||
modification.tags = (tiddler.fields.tags || []).slice(0);
|
||||
modification.tags.splice(p,1);
|
||||
if(modification.tags.length === 0) {
|
||||
modification.tags = undefined;
|
||||
}
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
|
||||
}
|
||||
}
|
||||
@@ -100,7 +103,7 @@ FieldManglerWidget.prototype.handleRemoveTagEvent = function(event) {
|
||||
FieldManglerWidget.prototype.handleAddTagEvent = function(event) {
|
||||
var tiddler = this.wiki.getTiddler(this.mangleTitle);
|
||||
if(tiddler && typeof event.param === "string" && event.param !== "") {
|
||||
var modification = {};
|
||||
var modification = this.wiki.getModificationFields();
|
||||
modification.tags = (tiddler.fields.tags || []).slice(0);
|
||||
$tw.utils.pushTop(modification.tags,event.param);
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,modification));
|
||||
|
||||
@@ -91,7 +91,7 @@ LinkWidget.prototype.handleClickEvent = function (event) {
|
||||
this.dispatchEvent({
|
||||
type: "tw-navigate",
|
||||
navigateTo: this.to,
|
||||
navigateFromTitle: this.getVariable("currentTiddler"),
|
||||
navigateFromTitle: this.getVariable("storyTiddler"),
|
||||
navigateFromNode: this,
|
||||
navigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
|
||||
}
|
||||
@@ -114,21 +114,32 @@ LinkWidget.prototype.handleDragStartEvent = function(event) {
|
||||
this.dragImage.appendChild(inner);
|
||||
this.document.body.appendChild(this.dragImage);
|
||||
// Astoundingly, we need to cover the dragger up: http://www.kryogenix.org/code/browser/custom-drag-image.html
|
||||
var bounds = this.dragImage.firstChild.getBoundingClientRect(),
|
||||
cover = this.document.createElement("div");
|
||||
var cover = this.document.createElement("div");
|
||||
cover.className = "tw-tiddler-dragger-cover";
|
||||
cover.style.left = (bounds.left - 16) + "px";
|
||||
cover.style.top = (bounds.top - 16) + "px";
|
||||
cover.style.width = (bounds.width + 32) + "px";
|
||||
cover.style.height = (bounds.height + 32) + "px";
|
||||
cover.style.left = (inner.offsetLeft - 16) + "px";
|
||||
cover.style.top = (inner.offsetTop - 16) + "px";
|
||||
cover.style.width = (inner.offsetWidth + 32) + "px";
|
||||
cover.style.height = (inner.offsetHeight + 32) + "px";
|
||||
this.dragImage.appendChild(cover);
|
||||
// Set the data transfer properties
|
||||
var dataTransfer = event.dataTransfer;
|
||||
// First the image
|
||||
dataTransfer.effectAllowed = "copy";
|
||||
dataTransfer.setDragImage(this.dragImage.firstChild,-16,-16);
|
||||
if(dataTransfer.setDragImage) {
|
||||
dataTransfer.setDragImage(this.dragImage.firstChild,-16,-16);
|
||||
}
|
||||
// Then the data
|
||||
dataTransfer.clearData();
|
||||
dataTransfer.setData("text/vnd.tiddler",this.wiki.getTiddlerAsJson(this.to));
|
||||
dataTransfer.setData("text/plain",this.wiki.getTiddlerText(this.to,""));
|
||||
var jsonData = this.wiki.getTiddlerAsJson(this.to),
|
||||
textData = this.wiki.getTiddlerText(this.to,"");
|
||||
// IE doesn't like these content types
|
||||
if(!$tw.browser.isIE) {
|
||||
dataTransfer.setData("text/vnd.tiddler",jsonData);
|
||||
dataTransfer.setData("text/plain",textData);
|
||||
dataTransfer.setData("text/x-moz-url","data:text/vnd.tiddler," + encodeURI(jsonData));
|
||||
}
|
||||
dataTransfer.setData("URL","data:text/vnd.tiddler," + encodeURI(jsonData));
|
||||
dataTransfer.setData("Text",textData);
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -70,131 +70,154 @@ NavigatorWidget.prototype.refresh = function(changedTiddlers) {
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.getStoryList = function() {
|
||||
this.storyList = this.wiki.getTiddlerList(this.storyTitle);
|
||||
return this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.saveStoryList = function() {
|
||||
NavigatorWidget.prototype.saveStoryList = function(storyList) {
|
||||
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
|
||||
this.wiki.addTiddler(new $tw.Tiddler({
|
||||
title: this.storyTitle
|
||||
},storyTiddler,{list: this.storyList}));
|
||||
this.wiki.addTiddler(new $tw.Tiddler(
|
||||
{title: this.storyTitle},
|
||||
storyTiddler,
|
||||
{list: storyList}
|
||||
));
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.findTitleInStory = function(title,defaultIndex) {
|
||||
for(var t=0; t<this.storyList.length; t++) {
|
||||
if(this.storyList[t] === title) {
|
||||
return t;
|
||||
NavigatorWidget.prototype.findTitleInStory = function(storyList,title,defaultIndex) {
|
||||
var p = storyList.indexOf(title);
|
||||
return p === -1 ? defaultIndex : p;
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
|
||||
var storyList = this.getStoryList();
|
||||
if(storyList) {
|
||||
// See if the tiddler is already there
|
||||
var slot = this.findTitleInStory(storyList,title,-1);
|
||||
// If not we need to add it
|
||||
if(slot === -1) {
|
||||
// First we try to find the position of the story element we navigated from
|
||||
slot = this.findTitleInStory(storyList,fromTitle,-1) + 1;
|
||||
// Add the tiddler
|
||||
storyList.splice(slot,0,title);
|
||||
// Save the story
|
||||
this.saveStoryList(storyList);
|
||||
}
|
||||
}
|
||||
return defaultIndex;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Add a new record to the top of the history stack
|
||||
title: a title string or an array of title strings
|
||||
fromPageRect: page coordinates of the origin of the navigation
|
||||
*/
|
||||
NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {
|
||||
var titles = $tw.utils.isArray(title) ? title : [title];
|
||||
// Add a new record to the top of the history stack
|
||||
if(this.historyTitle) {
|
||||
var historyList = this.wiki.getTiddlerData(this.historyTitle,[]);
|
||||
$tw.utils.each(titles,function(title) {
|
||||
historyList.push({title: title, fromPageRect: fromPageRect});
|
||||
});
|
||||
this.wiki.setTiddlerData(this.historyTitle,historyList);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Handle a tw-navigate event
|
||||
*/
|
||||
NavigatorWidget.prototype.handleNavigateEvent = function(event) {
|
||||
if(this.storyTitle) {
|
||||
// Update the story tiddler if specified
|
||||
this.getStoryList();
|
||||
// See if the tiddler is already there
|
||||
var slot = this.findTitleInStory(event.navigateTo,-1);
|
||||
// If not we need to add it
|
||||
if(slot === -1) {
|
||||
// First we try to find the position of the story element we navigated from
|
||||
slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
|
||||
// Add the tiddler
|
||||
this.storyList.splice(slot,0,event.navigateTo);
|
||||
// Save the story
|
||||
this.saveStoryList();
|
||||
}
|
||||
}
|
||||
// Add a new record to the top of the history stack
|
||||
if(this.historyTitle) {
|
||||
var historyList = this.wiki.getTiddlerData(this.historyTitle,[]);
|
||||
historyList.push({title: event.navigateTo, fromPageRect: event.navigateFromClientRect});
|
||||
this.wiki.setTiddlerData(this.historyTitle,historyList);
|
||||
}
|
||||
this.addToStory(event.navigateTo,event.navigateFromTitle);
|
||||
this.addToHistory(event.navigateTo,event.navigateFromClientRect);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Close a specified tiddler
|
||||
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
|
||||
this.getStoryList();
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
storyList = this.getStoryList();
|
||||
// Look for tiddlers with this title to close
|
||||
var slot = this.findTitleInStory(event.tiddlerTitle,-1);
|
||||
if(slot !== -1) {
|
||||
this.storyList.splice(slot,1);
|
||||
this.saveStoryList();
|
||||
}
|
||||
this.removeTitleFromStory(storyList,title);
|
||||
this.saveStoryList(storyList);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Close all tiddlers
|
||||
NavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {
|
||||
this.storyList = [];
|
||||
this.saveStoryList();
|
||||
this.saveStoryList([]);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Close other tiddlers
|
||||
NavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {
|
||||
this.storyList = [event.tiddlerTitle];
|
||||
this.saveStoryList();
|
||||
var title = event.param || event.tiddlerTitle;
|
||||
this.saveStoryList([title]);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Place a tiddler in edit mode
|
||||
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
|
||||
this.getStoryList();
|
||||
// Replace the specified tiddler with a draft in edit mode
|
||||
var draftTiddler = this.getDraftTiddler(event.tiddlerTitle),
|
||||
gotOne = false;
|
||||
for(var t=this.storyList.length-1; t>=0; t--) {
|
||||
// Replace the first story instance of the original tiddler name with the draft title
|
||||
if(this.storyList[t] === event.tiddlerTitle) {
|
||||
if(!gotOne) {
|
||||
this.storyList[t] = draftTiddler.fields.title;
|
||||
gotOne = true;
|
||||
} else {
|
||||
this.storyList.splice(t,1);
|
||||
}
|
||||
} else if(this.storyList[t] === draftTiddler.fields.title) {
|
||||
// Remove any existing references to the draft
|
||||
this.storyList.splice(t,1);
|
||||
}
|
||||
}
|
||||
this.saveStoryList();
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
draftTiddler = this.makeDraftTiddler(title),
|
||||
draftTitle = draftTiddler.fields.title,
|
||||
storyList = this.getStoryList();
|
||||
this.removeTitleFromStory(storyList,draftTitle);
|
||||
this.replaceFirstTitleInStory(storyList,title,draftTitle);
|
||||
this.addToHistory(draftTitle,event.navigateFromClientRect);
|
||||
this.saveStoryList(storyList);
|
||||
return false;
|
||||
};
|
||||
|
||||
// Delete a tiddler
|
||||
NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
|
||||
// Get the tiddler we're deleting
|
||||
var tiddler = this.wiki.getTiddler(event.tiddlerTitle);
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
tiddler = this.wiki.getTiddler(title),
|
||||
storyList = this.getStoryList();
|
||||
// Check if the tiddler we're deleting is in draft mode
|
||||
if(tiddler.hasField("draft.title")) {
|
||||
// Delete the original tiddler
|
||||
this.wiki.deleteTiddler(tiddler.fields["draft.of"]);
|
||||
var originalTitle = tiddler.fields["draft.of"];
|
||||
this.wiki.deleteTiddler(originalTitle);
|
||||
this.removeTitleFromStory(storyList,originalTitle);
|
||||
}
|
||||
// Delete this tiddler
|
||||
this.wiki.deleteTiddler(event.tiddlerTitle);
|
||||
this.wiki.deleteTiddler(title);
|
||||
// Remove the closed tiddler from the story
|
||||
this.getStoryList();
|
||||
// Look for tiddler with this title to close
|
||||
var slot = this.findTitleInStory(event.tiddlerTitle,-1);
|
||||
if(slot !== -1) {
|
||||
this.storyList.splice(slot,1);
|
||||
this.saveStoryList();
|
||||
}
|
||||
this.removeTitleFromStory(storyList,title);
|
||||
this.saveStoryList(storyList);
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
Create/reuse the draft tiddler for a given title
|
||||
*/
|
||||
NavigatorWidget.prototype.getDraftTiddler = function(targetTitle) {
|
||||
NavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {
|
||||
// See if there is already a draft tiddler for this tiddler
|
||||
var drafts = [];
|
||||
this.wiki.forEachTiddler(function(title,tiddler) {
|
||||
this.wiki.forEachTiddler({includeSystem: true},function(title,tiddler) {
|
||||
if(tiddler.fields["draft.title"] && tiddler.fields["draft.of"] === targetTitle) {
|
||||
drafts.push(tiddler);
|
||||
}
|
||||
@@ -234,71 +257,58 @@ NavigatorWidget.prototype.generateDraftTitle = function(title) {
|
||||
|
||||
// Take a tiddler out of edit mode, saving the changes
|
||||
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
||||
this.getStoryList();
|
||||
var storyTiddlerModified = false; // We have to special case saving the story tiddler itself
|
||||
for(var t=0; t<this.storyList.length; t++) {
|
||||
if(this.storyList[t] === event.tiddlerTitle) {
|
||||
var tiddler = this.wiki.getTiddler(event.tiddlerTitle);
|
||||
if(tiddler) {
|
||||
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
|
||||
draftOf = (tiddler.fields["draft.of"] || "").trim();
|
||||
if(draftTitle) {
|
||||
var isRename = draftOf !== draftTitle,
|
||||
isConfirmed = true;
|
||||
if(isRename && this.wiki.tiddlerExists(draftTitle)) {
|
||||
isConfirmed = confirm("Do you wish to overwrite the tiddler '" + draftTitle + "'?");
|
||||
}
|
||||
if(isConfirmed) {
|
||||
// Save the draft tiddler as the real tiddler
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{
|
||||
title: draftTitle,
|
||||
"draft.title": undefined,
|
||||
"draft.of": undefined
|
||||
},this.wiki.getModificationFields()));
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(event.tiddlerTitle);
|
||||
// Remove the original tiddler if we're renaming it
|
||||
if(isRename) {
|
||||
this.wiki.deleteTiddler(draftOf);
|
||||
}
|
||||
// Make the story record point to the newly saved tiddler
|
||||
this.storyList[t] = draftTitle;
|
||||
// Check if we're modifying the story tiddler itself
|
||||
if(draftTitle === this.storyTitle) {
|
||||
storyTiddlerModified = true;
|
||||
}
|
||||
}
|
||||
var title = event.param || event.tiddlerTitle,
|
||||
tiddler = this.wiki.getTiddler(title),
|
||||
storyList = this.getStoryList(),
|
||||
storyTiddlerModified = false; // We have to special case saving the story tiddler itself
|
||||
// Replace the original tiddler with the draft
|
||||
if(tiddler) {
|
||||
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
|
||||
draftOf = (tiddler.fields["draft.of"] || "").trim();
|
||||
if(draftTitle) {
|
||||
var isRename = draftOf !== draftTitle,
|
||||
isConfirmed = true;
|
||||
if(isRename && this.wiki.tiddlerExists(draftTitle)) {
|
||||
isConfirmed = confirm("Do you wish to overwrite the tiddler '" + draftTitle + "'?");
|
||||
}
|
||||
if(isConfirmed) {
|
||||
// Save the draft tiddler as the real tiddler
|
||||
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{
|
||||
title: draftTitle,
|
||||
"draft.title": undefined,
|
||||
"draft.of": undefined
|
||||
},this.wiki.getModificationFields()));
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(title);
|
||||
// Remove the original tiddler if we're renaming it
|
||||
if(isRename) {
|
||||
this.wiki.deleteTiddler(draftOf);
|
||||
}
|
||||
// Replace the draft in the story with the original
|
||||
this.replaceFirstTitleInStory(storyList,title,draftTitle);
|
||||
this.addToHistory(draftTitle,event.navigateFromClientRect);
|
||||
if(draftTitle !== this.storyTitle) {
|
||||
this.saveStoryList(storyList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!storyTiddlerModified) {
|
||||
this.saveStoryList();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Take a tiddler out of edit mode without saving the changes
|
||||
NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
||||
this.getStoryList();
|
||||
var storyTiddlerModified = false;
|
||||
for(var t=0; t<this.storyList.length; t++) {
|
||||
if(this.storyList[t] === event.tiddlerTitle) {
|
||||
var tiddler = this.wiki.getTiddler(event.tiddlerTitle);
|
||||
if(tiddler && tiddler.hasField("draft.title")) {
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(event.tiddlerTitle);
|
||||
// Make the story record point to the original tiddler
|
||||
this.storyList[t] = tiddler.fields["draft.title"];
|
||||
// Check if we're modifying the story tiddler itself
|
||||
if(tiddler.fields["draft.title"] === this.storyTitle) {
|
||||
storyTiddlerModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!storyTiddlerModified) {
|
||||
this.saveStoryList();
|
||||
// Flip the specified tiddler from draft back to the original
|
||||
var draftTitle = event.param || event.tiddlerTitle,
|
||||
draftTiddler = this.wiki.getTiddler(draftTitle),
|
||||
originalTitle = draftTiddler.fields["draft.of"],
|
||||
storyList = this.getStoryList();
|
||||
if(draftTiddler && originalTitle) {
|
||||
// Remove the draft tiddler
|
||||
this.wiki.deleteTiddler(draftTitle);
|
||||
this.replaceFirstTitleInStory(storyList,draftTitle,originalTitle);
|
||||
this.addToHistory(originalTitle,event.navigateFromClientRect);
|
||||
this.saveStoryList(storyList);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -306,18 +316,11 @@ NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
||||
// Create a new draft tiddler
|
||||
NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
||||
// Get the story details
|
||||
this.getStoryList();
|
||||
var storyList = this.getStoryList();
|
||||
// Get the template tiddler if there is one
|
||||
var templateTiddler = this.wiki.getTiddler(event.param);
|
||||
// Create the new tiddler
|
||||
var baseTitle = (templateTiddler && templateTiddler.fields.title) || "New Tiddler",
|
||||
title;
|
||||
for(var t=0; true; t++) {
|
||||
title = baseTitle + (t ? " " + t : "");
|
||||
if(!this.wiki.tiddlerExists(title)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var title = this.wiki.generateNewTitle((templateTiddler && templateTiddler.fields.title) || "New Tiddler");
|
||||
var tiddler = new $tw.Tiddler(this.wiki.getCreationFields(),{
|
||||
text: "Newly created tiddler",
|
||||
title: title
|
||||
@@ -326,22 +329,22 @@ NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
||||
// Create the draft tiddler
|
||||
var draftTitle = this.generateDraftTitle(title),
|
||||
draftTiddler = new $tw.Tiddler({
|
||||
text: "Type the text for the new tiddler"
|
||||
},templateTiddler,{
|
||||
text: ""
|
||||
},templateTiddler,
|
||||
this.wiki.getCreationFields(),
|
||||
{
|
||||
title: draftTitle,
|
||||
"draft.title": title,
|
||||
"draft.of": title
|
||||
},this.wiki.getModificationFields());
|
||||
this.wiki.addTiddler(draftTiddler);
|
||||
// Update the story to insert the new draft at the top
|
||||
var slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
|
||||
this.storyList.splice(slot,0,draftTitle);
|
||||
var slot = storyList.indexOf(event.navigateFromTitle);
|
||||
storyList.splice(slot + 1,0,draftTitle);
|
||||
// Save the updated story
|
||||
this.saveStoryList();
|
||||
this.saveStoryList(storyList);
|
||||
// Add a new record to the top of the history stack
|
||||
var history = this.wiki.getTiddlerData(this.historyTitle,[]);
|
||||
history.push({title: draftTitle});
|
||||
this.wiki.setTiddlerData(this.historyTitle,history);
|
||||
this.addToHistory(draftTitle);
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -349,8 +352,8 @@ NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
||||
NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
|
||||
var self = this;
|
||||
// Get the story and history details
|
||||
this.getStoryList();
|
||||
var history = this.wiki.getTiddlerData(this.historyTitle,[]);
|
||||
var storyList = this.getStoryList();
|
||||
var history = [];
|
||||
// Get the tiddlers
|
||||
var tiddlers = [];
|
||||
try {
|
||||
@@ -359,25 +362,25 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
|
||||
}
|
||||
// Process each tiddler
|
||||
$tw.utils.each(tiddlers,function(tiddlerFields) {
|
||||
// Generate a unique title for the tiddler
|
||||
var title = self.wiki.generateNewTitle(tiddlerFields.title);
|
||||
var title = tiddlerFields.title;
|
||||
// Add it to the store
|
||||
self.wiki.addTiddler(new $tw.Tiddler(
|
||||
var imported = self.wiki.importTiddler(new $tw.Tiddler(
|
||||
self.wiki.getCreationFields(),
|
||||
self.wiki.getModificationFields(),
|
||||
tiddlerFields,
|
||||
{title: title}
|
||||
tiddlerFields
|
||||
));
|
||||
// Add it to the story
|
||||
if(self.storyList.indexOf(title) === -1) {
|
||||
self.storyList.unshift(title);
|
||||
if(imported) {
|
||||
// Add it to the story
|
||||
if(storyList.indexOf(title) === -1) {
|
||||
storyList.unshift(title);
|
||||
}
|
||||
// And to history
|
||||
history.push(title);
|
||||
}
|
||||
// And to history
|
||||
history.push({title: title});
|
||||
});
|
||||
// Save the updated story and history
|
||||
this.saveStoryList();
|
||||
this.wiki.setTiddlerData(this.historyTitle,history);
|
||||
this.saveStoryList(storyList);
|
||||
this.addToHistory(history);
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
129
core/modules/widgets/radio.js
Normal file
129
core/modules/widgets/radio.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/radio.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Radio widget
|
||||
|
||||
Will set a field to the selected value:
|
||||
|
||||
```
|
||||
<$radio field="myfield" value="check 1">one</$radio>
|
||||
<$radio field="myfield" value="check 2">two</$radio>
|
||||
<$radio field="myfield" value="check 3">three</$radio>
|
||||
```
|
||||
|
||||
|Parameter |Description |h
|
||||
|tiddler |Name of the tiddler in which the field should be set. Defaults to current tiddler |
|
||||
|field |The name of the field to be set |
|
||||
|value |The value to set |
|
||||
|class |Optional class name(s) |
|
||||
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var RadioWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
RadioWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
RadioWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Save the parent dom node
|
||||
this.parentDomNode = parent;
|
||||
// Compute our attributes
|
||||
this.computeAttributes();
|
||||
// Execute our logic
|
||||
this.execute();
|
||||
// Create our elements
|
||||
this.labelDomNode = this.document.createElement("label");
|
||||
this.labelDomNode.setAttribute("class",this.radioClass);
|
||||
this.inputDomNode = this.document.createElement("input");
|
||||
this.inputDomNode.setAttribute("type","radio");
|
||||
if(this.getValue() == this.radioValue) {
|
||||
this.inputDomNode.setAttribute("checked","true");
|
||||
}
|
||||
this.labelDomNode.appendChild(this.inputDomNode);
|
||||
this.spanDomNode = this.document.createElement("span");
|
||||
this.labelDomNode.appendChild(this.spanDomNode);
|
||||
// Add a click event handler
|
||||
$tw.utils.addEventListeners(this.inputDomNode,[
|
||||
{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}
|
||||
]);
|
||||
// Insert the label into the DOM and render any children
|
||||
parent.insertBefore(this.labelDomNode,nextSibling);
|
||||
this.renderChildren(this.spanDomNode,null);
|
||||
this.domNodes.push(this.labelDomNode);
|
||||
};
|
||||
|
||||
RadioWidget.prototype.getValue = function() {
|
||||
var tiddler = this.wiki.getTiddler(this.radioTitle);
|
||||
return tiddler && tiddler.getFieldString(this.radioField);
|
||||
};
|
||||
|
||||
RadioWidget.prototype.setValue = function() {
|
||||
if(this.radioField) {
|
||||
var tiddler = this.wiki.getTiddler(this.radioTitle),
|
||||
addition = {};
|
||||
addition[this.radioField] = this.radioValue;
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
||||
}
|
||||
};
|
||||
|
||||
RadioWidget.prototype.handleChangeEvent = function(event) {
|
||||
if(this.inputDomNode.checked) {
|
||||
this.setValue();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
RadioWidget.prototype.execute = function() {
|
||||
// Get the parameters from the attributes
|
||||
this.radioTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
|
||||
this.radioField = this.getAttribute("field");
|
||||
this.radioValue = this.getAttribute("value");
|
||||
this.radioClass = this.getAttribute("class","");
|
||||
if(this.radioClass !== "") {
|
||||
this.radioClass += " ";
|
||||
}
|
||||
this.radioClass += "tw-radio";
|
||||
// Make the child widgets
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
RadioWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.value || changedAttributes["class"]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
var refreshed = false;
|
||||
if(changedTiddlers[this.radioTitle]) {
|
||||
this.inputDomNode.checked = this.getValue() === this.radioValue;
|
||||
refreshed = true;
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers) || refreshed;
|
||||
}
|
||||
};
|
||||
|
||||
exports.radio = RadioWidget;
|
||||
|
||||
})();
|
||||
53
core/modules/widgets/raw.js
Normal file
53
core/modules/widgets/raw.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/raw.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Raw widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var RawWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
RawWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
RawWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.execute();
|
||||
var div = this.document.createElement("div");
|
||||
div.innerHTML=this.parseTreeNode.html;
|
||||
parent.insertBefore(div,nextSibling);
|
||||
this.domNodes.push(div);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
RawWidget.prototype.execute = function() {
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
RawWidget.prototype.refresh = function(changedTiddlers) {
|
||||
return false;
|
||||
};
|
||||
|
||||
exports.raw = RawWidget;
|
||||
|
||||
})();
|
||||
@@ -157,7 +157,8 @@ RevealWidget.prototype.refresh = function(changedTiddlers) {
|
||||
} else {
|
||||
var refreshed = false;
|
||||
if(changedTiddlers[this.stateTitle]) {
|
||||
this.updateState();
|
||||
// this.updateState();
|
||||
this.refreshSelf();
|
||||
refreshed = true;
|
||||
}
|
||||
return this.refreshChildren(changedTiddlers) || refreshed;
|
||||
|
||||
@@ -28,8 +28,10 @@ Render this widget into the DOM
|
||||
*/
|
||||
TextNodeWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
var textNode = this.document.createTextNode(this.parseTreeNode.text);
|
||||
var text = this.getAttribute("text",this.parseTreeNode.text),
|
||||
textNode = this.document.createTextNode(text);
|
||||
parent.insertBefore(textNode,nextSibling);
|
||||
this.domNodes.push(textNode);
|
||||
};
|
||||
|
||||
@@ -148,8 +148,9 @@ ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsDate = function(format) {
|
||||
var value = this.getValue();
|
||||
if(value) {
|
||||
format = format || "YYYY MM DD 0hh:0mm";
|
||||
var value = $tw.utils.parseDate(this.getValue());
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.formatDateString(value,format);
|
||||
} else {
|
||||
return "";
|
||||
@@ -157,8 +158,8 @@ ViewWidget.prototype.getValueAsDate = function(format) {
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsRelativeDate = function(format) {
|
||||
var value = this.getValue();
|
||||
if(value) {
|
||||
var value = $tw.utils.parseDate(this.getValue());
|
||||
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
|
||||
return $tw.utils.getRelativeDate((new Date()) - (new Date(value))).description;
|
||||
} else {
|
||||
return "";
|
||||
|
||||
@@ -143,29 +143,34 @@ Widget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue)
|
||||
if($tw.utils.hop($tw.macros,name)) {
|
||||
var macro = $tw.macros[name],
|
||||
args = [];
|
||||
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
|
||||
paramInfo, paramValue;
|
||||
// Step through each of the parameters in the macro definition
|
||||
for(var p=0; p<macro.params.length; p++) {
|
||||
// Check if we've got a macro call parameter with the same name
|
||||
paramInfo = macro.params[p];
|
||||
paramValue = undefined;
|
||||
for(var m=0; m<actualParams.length; m++) {
|
||||
if(actualParams[m].name === paramInfo.name) {
|
||||
paramValue = actualParams[m].value;
|
||||
if(macro.params.length > 0) {
|
||||
var nextAnonParameter = 0, // Next candidate anonymous parameter in macro call
|
||||
paramInfo, paramValue;
|
||||
// Step through each of the parameters in the macro definition
|
||||
for(var p=0; p<macro.params.length; p++) {
|
||||
// Check if we've got a macro call parameter with the same name
|
||||
paramInfo = macro.params[p];
|
||||
paramValue = undefined;
|
||||
for(var m=0; m<actualParams.length; m++) {
|
||||
if(actualParams[m].name === paramInfo.name) {
|
||||
paramValue = actualParams[m].value;
|
||||
}
|
||||
}
|
||||
// If not, use the next available anonymous macro call parameter
|
||||
while(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {
|
||||
nextAnonParameter++;
|
||||
}
|
||||
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
|
||||
paramValue = actualParams[nextAnonParameter++].value;
|
||||
}
|
||||
// If we've still not got a value, use the default, if any
|
||||
paramValue = paramValue || paramInfo["default"] || "";
|
||||
// Save the parameter
|
||||
args.push(paramValue);
|
||||
}
|
||||
// If not, use the next available anonymous macro call parameter
|
||||
while(nextAnonParameter < actualParams.length && actualParams[nextAnonParameter].name) {
|
||||
nextAnonParameter++;
|
||||
}
|
||||
if(paramValue === undefined && nextAnonParameter < actualParams.length) {
|
||||
paramValue = actualParams[nextAnonParameter++].value;
|
||||
}
|
||||
// If we've still not got a value, use the default, if any
|
||||
paramValue = paramValue || paramInfo["default"] || "";
|
||||
// Save the parameter
|
||||
args.push(paramValue);
|
||||
}
|
||||
else for(var i=0; i<actualParams.length; ++i) {
|
||||
args.push(actualParams[i].value);
|
||||
}
|
||||
return macro.run.apply(this,args)
|
||||
} else {
|
||||
|
||||
@@ -173,11 +173,11 @@ exports.tiddlerExists = function(title) {
|
||||
Generate an unused title from the specified base
|
||||
*/
|
||||
exports.generateNewTitle = function(baseTitle) {
|
||||
var c = 0;
|
||||
do {
|
||||
var title = baseTitle + (c ? " " + (c + 1) : "");
|
||||
c++;
|
||||
} while(this.tiddlerExists(title));
|
||||
var c = 0,
|
||||
title = baseTitle;
|
||||
while(this.tiddlerExists(title)) {
|
||||
title = baseTitle + " " + (++c);
|
||||
};
|
||||
return title;
|
||||
};
|
||||
|
||||
@@ -204,10 +204,29 @@ exports.addTiddler = function(tiddler) {
|
||||
// Get the title
|
||||
var title = tiddler.fields.title;
|
||||
// Save the tiddler
|
||||
this.tiddlers[title] = tiddler;
|
||||
this.clearCache(title);
|
||||
this.clearGlobalCache();
|
||||
this.enqueueTiddlerEvent(title);
|
||||
if(title) {
|
||||
this.tiddlers[title] = tiddler;
|
||||
this.clearCache(title);
|
||||
this.clearGlobalCache();
|
||||
this.enqueueTiddlerEvent(title);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Like addTiddler() except it will silently reject any plugin tiddlers that are older than the currently loaded version. Returns true if the tiddler was imported
|
||||
*/
|
||||
exports.importTiddler = function(tiddler) {
|
||||
var existingTiddler = this.getTiddler(tiddler.fields.title);
|
||||
// Check if we're dealing with a plugin
|
||||
if(tiddler && tiddler.hasField("plugin-type") && tiddler.hasField("version") && existingTiddler && existingTiddler.hasField("plugin-type") && existingTiddler.hasField("version")) {
|
||||
// Reject the incoming plugin if it is older
|
||||
if($tw.utils.checkVersions(existingTiddler.fields.version,tiddler.fields.version)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Fall through to adding the tiddler
|
||||
this.addTiddler(tiddler);
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -238,14 +257,23 @@ exports.getModificationFields = function() {
|
||||
};
|
||||
|
||||
/*
|
||||
Return a sorted array of non-system tiddler titles, optionally filtered by a tag
|
||||
Return a sorted array of tiddler titles. Options include:
|
||||
sortField: field to sort by
|
||||
excludeTag: tag to exclude
|
||||
includeSystem: whether to include system tiddlers (defaults to false)
|
||||
*/
|
||||
exports.getTiddlers = function(sortField,excludeTag) {
|
||||
sortField = sortField || "title";
|
||||
var tiddlers = [], t, titles = [];
|
||||
exports.getTiddlers = function(options) {
|
||||
options = options || {};
|
||||
var self = this,
|
||||
sortField = options.sortField || "title",
|
||||
tiddlers = [], t, titles = [];
|
||||
for(t in this.tiddlers) {
|
||||
if($tw.utils.hop(this.tiddlers,t) && !this.isSystemTiddler(t) && (!excludeTag || !this.tiddlers[t].hasTag(excludeTag))) {
|
||||
tiddlers.push(this.tiddlers[t]);
|
||||
if($tw.utils.hop(this.tiddlers,t)) {
|
||||
if(options.includeSystem || !this.isSystemTiddler(t)) {
|
||||
if(!options.excludeTag || !this.tiddlers[t].hasTag(excludeTag)) {
|
||||
tiddlers.push(this.tiddlers[t]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tiddlers.sort(function(a,b) {
|
||||
@@ -268,7 +296,7 @@ exports.getTiddlers = function(sortField,excludeTag) {
|
||||
};
|
||||
|
||||
exports.countTiddlers = function(excludeTag) {
|
||||
var tiddlers = this.getTiddlers(null,excludeTag);
|
||||
var tiddlers = this.getTiddlers({excludeTag: excludeTag});
|
||||
return $tw.utils.count(tiddlers);
|
||||
};
|
||||
|
||||
@@ -279,21 +307,27 @@ Sort an array of tiddler titles by a specified field
|
||||
isDescending: true if the sort should be descending
|
||||
isCaseSensitive: true if the sort should consider upper and lower case letters to be different
|
||||
*/
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive) {
|
||||
exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric) {
|
||||
var self = this;
|
||||
titles.sort(function(a,b) {
|
||||
if(sortField !== "title") {
|
||||
a = self.getTiddler(a).fields[sortField] || "";
|
||||
b = self.getTiddler(b).fields[sortField] || "";
|
||||
}
|
||||
if(!isCaseSensitive) {
|
||||
if(typeof a === "string") {
|
||||
a = a.toLowerCase();
|
||||
}
|
||||
if(typeof b === "string") {
|
||||
b = b.toLowerCase();
|
||||
if(!isNumeric || isNaN(a) || isNaN(b)) {
|
||||
if(!isCaseSensitive) {
|
||||
if(typeof a === "string") {
|
||||
a = a.toLowerCase();
|
||||
}
|
||||
if(typeof b === "string") {
|
||||
b = b.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
a-= 0;
|
||||
b-= 0;
|
||||
}
|
||||
if(a < b) {
|
||||
return isDescending ? +1 : -1;
|
||||
} else {
|
||||
@@ -306,12 +340,17 @@ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive) {
|
||||
});
|
||||
};
|
||||
|
||||
exports.forEachTiddler = function(/* [sortField,[excludeTag,]]callback */) {
|
||||
/*
|
||||
For every tiddler invoke a callback(title,tiddler) with `this` set to the wiki object. Options include:
|
||||
sortField: field to sort by
|
||||
excludeTag: tag to exclude
|
||||
includeSystem: whether to include system tiddlers (defaults to false)
|
||||
*/
|
||||
exports.forEachTiddler = function(/* [options,]callback */) {
|
||||
var arg = 0,
|
||||
sortField = arguments.length > 1 ? arguments[arg++] : null,
|
||||
excludeTag = arguments.length > 2 ? arguments[arg++] : null,
|
||||
options = arguments.length >= 2 ? arguments[arg++] : {},
|
||||
callback = arguments[arg++],
|
||||
titles = this.getTiddlers(sortField,excludeTag),
|
||||
titles = this.getTiddlers(options),
|
||||
t, tiddler;
|
||||
for(t=0; t<titles.length; t++) {
|
||||
tiddler = this.tiddlers[titles[t]];
|
||||
@@ -572,10 +611,14 @@ exports.setTiddlerData = function(title,data) {
|
||||
/*
|
||||
Return the content of a tiddler as an array containing each line
|
||||
*/
|
||||
exports.getTiddlerList = function(title) {
|
||||
exports.getTiddlerList = function(title,field,index) {
|
||||
if(index) {
|
||||
return $tw.utils.parseStringArray(this.extractTiddlerDataItem(title,index,""));
|
||||
}
|
||||
field = field || "list";
|
||||
var tiddler = this.getTiddler(title);
|
||||
if(tiddler && $tw.utils.isArray(tiddler.fields.list)) {
|
||||
return tiddler.fields.list.slice(0);
|
||||
if(tiddler) {
|
||||
return ($tw.utils.parseStringArray(tiddler.fields[field]) || []).slice(0);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
@@ -740,7 +783,7 @@ exports.parseTextReference = function(title,field,index,options) {
|
||||
if(text === undefined) {
|
||||
text = "";
|
||||
}
|
||||
return this.parseText("text/vnd.tiddlywiki",text,options);
|
||||
return this.parseText("text/vnd.tiddlywiki",text.toString(),options);
|
||||
} else if(index) {
|
||||
text = this.extractTiddlerDataItem(title,index,"");
|
||||
return this.parseText("text/vnd.tiddlywiki",text,options);
|
||||
@@ -782,7 +825,7 @@ exports.makeWidget = function(parser,options) {
|
||||
// Create the widget
|
||||
return new widget.widget(widgetNode,{
|
||||
wiki: this,
|
||||
document: options.document || $tw.document,
|
||||
document: options.document || $tw.fakeDocument,
|
||||
parentWidget: options.parentWidget
|
||||
});
|
||||
};
|
||||
@@ -801,7 +844,7 @@ exports.renderText = function(outputType,textType,text,options) {
|
||||
options = options || {};
|
||||
var parser = this.parseText(textType,text,options),
|
||||
widgetNode = this.makeWidget(parser,options);
|
||||
var container = $tw.document.createElement("div");
|
||||
var container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
return outputType === "text/html" ? container.innerHTML : container.textContent;
|
||||
};
|
||||
@@ -819,7 +862,7 @@ exports.renderTiddler = function(outputType,title,options) {
|
||||
options = options || {};
|
||||
var parser = this.parseTiddler(title),
|
||||
widgetNode = this.makeWidget(parser,options);
|
||||
var container = $tw.document.createElement("div");
|
||||
var container = $tw.fakeDocument.createElement("div");
|
||||
widgetNode.render(container,null);
|
||||
return outputType === "text/html" ? container.innerHTML : container.textContent;
|
||||
};
|
||||
@@ -909,7 +952,7 @@ exports.search = function(text,options) {
|
||||
searchTermsRegExps = [new RegExp("(" + $tw.utils.escapeRegExp(text) + ")",flags)];
|
||||
}
|
||||
} else {
|
||||
terms = text.replace(/( +)/g," ").split(" ");
|
||||
terms = text.split(/ +/);
|
||||
if(terms.length === 1 && terms[0] === "") {
|
||||
searchTermsRegExps = null;
|
||||
} else {
|
||||
@@ -993,16 +1036,24 @@ exports.getTiddlerText = function(title,defaultText) {
|
||||
};
|
||||
|
||||
/*
|
||||
Read an array of browser File objects, invoking callback(tiddlerFields) for each loaded file
|
||||
Read an array of browser File objects, invoking callback(tiddlerFieldsArray) once they're all read
|
||||
*/
|
||||
exports.readFiles = function(files,callback) {
|
||||
var result = [],
|
||||
outstanding = files.length;
|
||||
for(var f=0; f<files.length; f++) {
|
||||
this.readFile(files[f],callback);
|
||||
this.readFile(files[f],function(tiddlerFieldsArray) {
|
||||
result.push.apply(result,tiddlerFieldsArray);
|
||||
if(--outstanding === 0) {
|
||||
callback(result);
|
||||
}
|
||||
});
|
||||
};
|
||||
return files.length;
|
||||
};
|
||||
|
||||
/*
|
||||
Read a browser File object, invoking callback(tiddlerFields) with the tiddler fields object
|
||||
Read a browser File object, invoking callback(tiddlerFieldsArray) with an array of tiddler fields objects
|
||||
*/
|
||||
exports.readFile = function(file,callback) {
|
||||
// Get the type, falling back to the filename extension
|
||||
@@ -1025,21 +1076,27 @@ exports.readFile = function(file,callback) {
|
||||
// Onload
|
||||
reader.onload = function(event) {
|
||||
// Deserialise the file contents
|
||||
var tiddlerFields = {title: file.name || "Untitled", type: type};
|
||||
var text = event.target.result,
|
||||
tiddlerFields = {title: file.name || "Untitled", type: type};
|
||||
// Are we binary?
|
||||
if(isBinary) {
|
||||
// The base64 section starts after the first comma in the data URI
|
||||
var commaPos = event.target.result.indexOf(",");
|
||||
var commaPos = text.indexOf(",");
|
||||
if(commaPos !== -1) {
|
||||
tiddlerFields.text = event.target.result.substr(commaPos+1);
|
||||
callback(tiddlerFields);
|
||||
tiddlerFields.text = text.substr(commaPos+1);
|
||||
callback([tiddlerFields]);
|
||||
}
|
||||
} else {
|
||||
var tiddlers = self.deserializeTiddlers(type,event.target.result,tiddlerFields);
|
||||
if(tiddlers) {
|
||||
$tw.utils.each(tiddlers,function(tiddlerFields) {
|
||||
callback(tiddlerFields);
|
||||
// Check whether this is an encrypted TiddlyWiki file
|
||||
var encryptedJson = $tw.utils.extractEncryptedStoreArea(text);
|
||||
if(encryptedJson) {
|
||||
// If so, attempt to decrypt it with the current password
|
||||
$tw.utils.decryptStoreAreaInteractive(encryptedJson,function(tiddlers) {
|
||||
callback(tiddlers);
|
||||
});
|
||||
} else {
|
||||
// Otherwise, just try to deserialise any tiddlers in the file
|
||||
callback(self.deserializeTiddlers(type,text,tiddlerFields));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
5
core/templates/MOTW.html.tid
Normal file
5
core/templates/MOTW.html.tid
Normal file
@@ -0,0 +1,5 @@
|
||||
title: $:/core/templates/MOTW.html
|
||||
|
||||
\rules only filteredtranscludeinline transcludeinline entity
|
||||
<!-- The following comment is called a MOTW comment and is necessary for the TiddlyIE Internet Explorer extension -->
|
||||
<!-- saved from url=(0021)http://tiddlywiki.com -->
|
||||
3
core/templates/alltiddlers.content.tid
Normal file
3
core/templates/alltiddlers.content.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/core/templates/alltiddlers.content
|
||||
|
||||
{{{ [!is[system]sort[title]] ||$:/core/templates/static-tiddler}}}
|
||||
28
core/templates/alltiddlers.template.html.tid
Normal file
28
core/templates/alltiddlers.template.html.tid
Normal file
@@ -0,0 +1,28 @@
|
||||
title: $:/core/templates/alltiddlers.template.html
|
||||
type: text/vnd.tiddlywiki-html
|
||||
|
||||
\define tw-wikilink-template() #$uri_encoded$
|
||||
\rules only filteredtranscludeinline transcludeinline
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name="generator" content="TiddlyWiki" />
|
||||
<meta name="tiddlywiki-version" content="{{$:/core/templates/version}}" />
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
||||
<title>{{$:/core/wiki/title}}</title>
|
||||
<div id="styleArea">
|
||||
{{{ [is[system]type[text/css]] ||$:/core/templates/css-tiddler}}}
|
||||
</div>
|
||||
<style type="text/css">
|
||||
{{{ [tag[$:/tags/stylesheet]] [is[shadow]tag[$:/tags/stylesheet]] ||$:/core/templates/wikified-tiddler}}}
|
||||
</style>
|
||||
</head>
|
||||
<body class="tw-body">
|
||||
{{$:/StaticBanner||$:/core/templates/html-tiddler}}
|
||||
<section class="story-river">
|
||||
{{$:/core/templates/alltiddlers.content||$:/core/templates/html-tiddler}}
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/core/save/all
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[tiddler]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
[is[tiddler]] -[type[text/css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
title: $:/core/save/empty
|
||||
|
||||
\define saveTiddlerFilter()
|
||||
[is[system]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
[is[system]] -[type[text/css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]]
|
||||
\end
|
||||
{{$:/core/templates/tiddlywiki5.html}}
|
||||
|
||||
5
core/templates/static-tiddler.tid
Normal file
5
core/templates/static-tiddler.tid
Normal file
@@ -0,0 +1,5 @@
|
||||
title: $:/core/templates/static-tiddler
|
||||
|
||||
<a name=<<currentTiddler>>>
|
||||
<$transclude tiddler="$:/core/ui/ViewTemplate"/>
|
||||
</a>
|
||||
@@ -10,6 +10,7 @@ type: text/vnd.tiddlywiki-html
|
||||
<meta name="generator" content="TiddlyWiki" />
|
||||
<meta name="tiddlywiki-version" content="{{$:/core/templates/version}}" />
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
||||
<title>{{$:/core/wiki/title}}</title>
|
||||
<div id="styleArea">
|
||||
{{{ [is[system]type[text/css]] ||$:/core/templates/css-tiddler}}}
|
||||
@@ -20,6 +21,6 @@ type: text/vnd.tiddlywiki-html
|
||||
</head>
|
||||
<body class="tw-body">
|
||||
{{$:/StaticBanner||$:/core/templates/html-tiddler}}
|
||||
{{$:/core/ui/PageTemplate||$:/core/templates/html-tiddler}}
|
||||
{{$:/core/ui/PageMacros||$:/core/templates/html-tiddler}}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,6 +8,7 @@ title: $:/core/templates/static.tiddler.html
|
||||
<meta name="generator" content="TiddlyWiki" />
|
||||
<meta name="tiddlywiki-version" content="`{{$:/core/templates/version}}`" />
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
||||
<link rel="stylesheet" href="static.css">
|
||||
<title>`{{$:/core/wiki/title}}`</title>
|
||||
</head>
|
||||
|
||||
@@ -6,7 +6,7 @@ title: $:/core/templates/store.area.template.html
|
||||
`</div>`
|
||||
</$reveal>
|
||||
<$reveal type="match" state="$:/isEncrypted" text="yes">
|
||||
`<!------------- Encrypted tiddlers --------->`
|
||||
`<!--~~ Encrypted tiddlers ~~-->`
|
||||
`<pre id="encryptedStoreArea" type="text/plain" style="display:none;">`
|
||||
<$encrypt filter=<<saveTiddlerFilter>>/>
|
||||
`</pre>`
|
||||
|
||||
@@ -2,8 +2,9 @@ title: $:/core/templates/tiddlywiki5.html
|
||||
|
||||
\rules only filteredtranscludeinline transcludeinline
|
||||
<!doctype html>
|
||||
<html>
|
||||
{{$:/core/templates/MOTW.html}}<html>
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Force IE standards mode for Intranet and HTA - should be the first meta -->
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name="application-name" content="TiddlyWiki" />
|
||||
<meta name="generator" content="TiddlyWiki" />
|
||||
@@ -13,38 +14,35 @@ title: $:/core/templates/tiddlywiki5.html
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
|
||||
<link id="faviconLink" rel="shortcut icon" href="favicon.ico">
|
||||
<title>{{$:/core/wiki/title}}</title>
|
||||
<!----------- This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ----------->
|
||||
<!--~~ This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ~~-->
|
||||
|
||||
<!----------- Raw markup ----------->
|
||||
<!--~~ Raw markup ~~-->
|
||||
{{{ [tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
|
||||
</head>
|
||||
<body class="tw-body">
|
||||
<!----------- Static styles ----------->
|
||||
<!--~~ Static styles ~~-->
|
||||
<div id="styleArea">
|
||||
{{{ [is[system]type[text/css]] ||$:/core/templates/css-tiddler}}}
|
||||
</div>
|
||||
<!----------- Static content for Google and browsers without JavaScript ----------->
|
||||
<!--~~ Static content for Google and browsers without JavaScript ~~-->
|
||||
<noscript>
|
||||
<div id="splashArea">
|
||||
{{$:/core/templates/static.area}}
|
||||
</div>
|
||||
</noscript>
|
||||
<!----------- Ordinary tiddlers ----------->
|
||||
<!--~~ Ordinary tiddlers ~~-->
|
||||
{{$:/core/templates/store.area.template.html}}
|
||||
<!----------- Library modules ----------->
|
||||
<!--~~ Library modules ~~-->
|
||||
<div id="libraryModules" style="display:none;">
|
||||
{{{ [is[system]type[application/javascript]library[yes]] ||$:/core/templates/javascript-tiddler}}}
|
||||
</div>
|
||||
<!----------- Boot kernel prologue ----------->
|
||||
<!--~~ Boot kernel prologue ~~-->
|
||||
<div id="bootKernelPrefix" style="display:none;">
|
||||
{{ $:/boot/bootprefix.js ||$:/core/templates/javascript-tiddler}}
|
||||
</div>
|
||||
<!----------- Plugin modules ----------->
|
||||
<div id="modules" style="display:none;">
|
||||
{{{ [is[system]type[application/javascript]has[module-type]] ||$:/core/templates/module-tiddler}}}
|
||||
</div>
|
||||
<!----------- Boot kernel ----------->
|
||||
<!--~~ Boot kernel ~~-->
|
||||
<div id="bootKernel" style="display:none;">
|
||||
{{ $:/boot/boot.js ||$:/core/templates/javascript-tiddler}}
|
||||
</div>
|
||||
|
||||
3
core/ui/AdvancedSearch.tid
Normal file
3
core/ui/AdvancedSearch.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/AdvancedSearch
|
||||
|
||||
<div class="tw-advanced-search"><<tabs "[is[shadow]!has[draft.of]tag[$:/tags/AdvancedSearch]] [!is[shadow]!has[draft.of]tag[$:/tags/AdvancedSearch]] +[tag[$:/tags/AdvancedSearch]]" "$:/core/ui/AdvancedSearch/System">></div>
|
||||
27
core/ui/AdvancedSearch/Shadows.tid
Normal file
27
core/ui/AdvancedSearch/Shadows.tid
Normal file
@@ -0,0 +1,27 @@
|
||||
title: $:/core/ui/AdvancedSearch/Shadows
|
||||
tags: $:/tags/AdvancedSearch
|
||||
caption: Shadows
|
||||
|
||||
<$linkcatcher to="$:/temp/advancedsearch">
|
||||
|
||||
Search for shadow tiddlers:
|
||||
|
||||
<div class="tw-search"><$edit-text tiddler="$:/temp/advancedsearch" type="search" tag="input"/><$reveal state="$:/temp/advancedsearch" type="nomatch" text=""> <$link to="" class="btn-invisible">{{$:/core/images/close-button}}</$link></$reveal></div>
|
||||
|
||||
</$linkcatcher>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="nomatch" text="">
|
||||
|
||||
<div class="tw-search-results">
|
||||
|
||||
//<small><$count filter="[is[shadow]search{$:/temp/advancedsearch}]"/> matches</small>//
|
||||
|
||||
<$list filter="[is[shadow]search{$:/temp/advancedsearch}sort[title]limit[250]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
</div>
|
||||
|
||||
</$reveal>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="match" text="">
|
||||
|
||||
</$reveal>
|
||||
27
core/ui/AdvancedSearch/System.tid
Normal file
27
core/ui/AdvancedSearch/System.tid
Normal file
@@ -0,0 +1,27 @@
|
||||
title: $:/core/ui/AdvancedSearch/System
|
||||
tags: $:/tags/AdvancedSearch
|
||||
caption: System
|
||||
|
||||
<$linkcatcher to="$:/temp/advancedsearch">
|
||||
|
||||
Search for system tiddlers:
|
||||
|
||||
<div class="tw-search"><$edit-text tiddler="$:/temp/advancedsearch" type="search" tag="input"/><$reveal state="$:/temp/advancedsearch" type="nomatch" text=""> <$link to="" class="btn-invisible">{{$:/core/images/close-button}}</$link></$reveal></div>
|
||||
|
||||
</$linkcatcher>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="nomatch" text="">
|
||||
|
||||
<div class="tw-search-results">
|
||||
|
||||
//<small><$count filter="[is[system]search{$:/temp/advancedsearch}]"/> matches</small>//
|
||||
|
||||
<$list filter="[is[system]search{$:/temp/advancedsearch}sort[title]limit[250]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
</div>
|
||||
|
||||
</$reveal>
|
||||
|
||||
<$reveal state="$:/temp/advancedsearch" type="match" text="">
|
||||
|
||||
</$reveal>
|
||||
@@ -2,22 +2,13 @@ title: $:/core/ui/ControlPanel/Basics
|
||||
tags: $:/tags/ControlPanel
|
||||
caption: Basics
|
||||
|
||||
! Settings
|
||||
|
||||
|TiddlyWiki version |''<<version>>'' |
|
||||
|[[Title of this TiddlyWiki|SiteTitle]] |<$edit-text tiddler="SiteTitle" default="" tag="input"/> |
|
||||
|[[Subtitle|SiteSubtitle]] |<$edit-text tiddler="SiteSubtitle" default="" tag="input"/> |
|
||||
|[[Username for signing edits|$:/status/UserName]] |<$edit-text tiddler="$:/status/UserName" default="" tag="input"/> |
|
||||
|[[Animation duration|$:/config/AnimationDuration]] |<$edit-text tiddler="$:/config/AnimationDuration" default="" tag="input"/> |
|
||||
|[[DefaultTiddlers|$:/DefaultTiddlers]] |Choose which tiddlers are displayed at startup:<br> <$edit-text tag="textarea" tiddler="$:/DefaultTiddlers"/> |
|
||||
|
||||
! Info
|
||||
|
||||
!! Your Stuff
|
||||
|
||||
* Number of tiddlers: <$count filter="[!is[system]]"/>
|
||||
|
||||
!! TiddlyWiki's Stuff
|
||||
|
||||
* Number of system tiddlers: <$count filter="[is[system]]"/>
|
||||
* Number of shadow tiddlers: <$count filter="[is[shadow]]"/>
|
||||
** Number of over-ridden shadow tiddlers: <$count filter="[!is[system]is[shadow]]"/>
|
||||
|[[DefaultTiddlers|$:/DefaultTiddlers]] |Choose which tiddlers are displayed at startup:<br> <$edit-text tag="textarea" tiddler="$:/DefaultTiddlers"/><br>//Use [[double square brackets]] for titles with spaces. Or you can choose to <$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">retain story ordering</$button>// |
|
||||
|Tiddlers |''<$count filter="[!is[system]]"/>'' |
|
||||
|System tiddlers |''<$count filter="[is[system]]"/>'' |
|
||||
|Shadow tiddlers |''<$count filter="[is[shadow]]"/>'' |
|
||||
|Overridden shadow tiddlers |''<$count filter="[!is[system]is[shadow]]"/>'' |
|
||||
|
||||
@@ -2,6 +2,6 @@ title: $:/core/ui/ControlPanel/Plugins
|
||||
tags: $:/tags/ControlPanel
|
||||
caption: Plugins
|
||||
|
||||
<table><tbody><tr><th>Title</th><th>Description</th></tr><$list filter="[!has[draft.of]has[plugin-type]sort[title]]"><tr><td><$link to={{!!title}}><$view field="title"/></$link></td><td><$view field="description"/></td></tr></$list>
|
||||
<table><tbody><tr><th>Title</th><th>Description</th><th>Version</th></tr><$list filter="[!has[draft.of]has[plugin-type]sort[title]]"><tr><td><$link to={{!!title}}><$view field="title"/></$link></td><td><$view field="description"/></td><td><$view field="version"/></td></tr></$list>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -16,7 +16,14 @@ http://$(userName)$.tiddlyspot.com/backup/
|
||||
|
||||
|[[Wiki name|$:/UploadName]] |<$edit-text tiddler="$:/UploadName" default="" tag="input"/> |
|
||||
|Password |<$password name="upload"/> |
|
||||
|Server URL |<$edit-text tiddler="$:/UploadURL" default="" tag="input"/> |
|
||||
|Backups |<<backupLink>> |
|
||||
|
||||
!! Advanced settings
|
||||
|
||||
|Server URL |<$edit-text tiddler="$:/UploadURL" default="" tag="input"/> |
|
||||
|Upload filename |<$edit-text tiddler="$:/UploadFilename" default="index.html" tag="input"/> |
|
||||
|Upload directory |<$edit-text tiddler="$:/UploadDir" default="." tag="input"/> |
|
||||
|Backup directory |<$edit-text tiddler="$:/UploadBackupDir" default="." tag="input"/> |
|
||||
|
||||
|
||||
//The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address//
|
||||
|
||||
@@ -8,6 +8,10 @@ caption: Tools
|
||||
|
||||
Browse for files on your computer to import their contents (the individual tiddlers within TiddlyWiki HTML files are imported separately). You can also drag and drop files directly to the browser window.
|
||||
|
||||
! Export
|
||||
|
||||
<$button message="tw-download-file" param="$:/core/templates/alltiddlers.template.html" class="btn-big-green">Download all tiddlers as static HTML {{$:/core/images/save-button}}</$button>
|
||||
|
||||
! Encryption
|
||||
|
||||
{{$:/snippets/encryptionstatus}}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
title: $:/core/ui/EditTemplate
|
||||
modifier: JeremyRuston
|
||||
|
||||
\define frame-classes()
|
||||
tw-tiddler-frame tw-tiddler-edit-frame $(missingTiddlerClass)$ $(shadowTiddlerClass)$ $(systemTiddlerClass)$
|
||||
\end
|
||||
<div class=<<frame-classes>>><$list filter="[is[shadow]!has[draft.of]tag[$:/tags/EditTemplate]] [!is[shadow]!has[draft.of]tag[$:/tags/EditTemplate]] +[tag[$:/tags/EditTemplate]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list></div>
|
||||
<$set name="storyTiddler" value=<<currentTiddler>>><div class=<<frame-classes>>><$list filter="[is[shadow]!has[draft.of]tag[$:/tags/EditTemplate]] [!is[shadow]!has[draft.of]tag[$:/tags/EditTemplate]] +[tag[$:/tags/EditTemplate]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list></div></$set>
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
title: $:/core/ui/EditTemplate/body
|
||||
tags: $:/tags/EditTemplate
|
||||
|
||||
\define prompt()
|
||||
Type the text for this tiddler
|
||||
\end
|
||||
<$reveal state="$:/ShowEditPreview" type="match" text="yes">
|
||||
//<$transclude tiddler="$:/core/ui/EditorHint"/>// <$button type="set" set="$:/ShowEditPreview" setTo="no">hide preview</$button>
|
||||
<em class="tw-edit"><$transclude tiddler="$:/core/ui/EditorHint"/></em> <$button type="set" set="$:/ShowEditPreview" setTo="no">hide preview</$button>
|
||||
<div class="tw-tiddler-preview">
|
||||
<div class="tw-tiddler-preview-preview">
|
||||
<$transclude />
|
||||
</div>
|
||||
<div class="tw-tiddler-preview-edit">
|
||||
<$edit field="text" class="tw-edit-texteditor"/>
|
||||
<$edit field="text" class="tw-edit-texteditor" placeholder=<<prompt>>/>
|
||||
</div>
|
||||
</div>
|
||||
</$reveal>
|
||||
<$reveal state="$:/ShowEditPreview" type="nomatch" text="yes">
|
||||
//<$transclude tiddler="$:/core/ui/EditorHint"/>// <$button type="set" set="$:/ShowEditPreview" setTo="yes">show preview</$button>
|
||||
<$edit field="text" class="tw-edit-texteditor"/>
|
||||
<em class="tw-edit"><$transclude tiddler="$:/core/ui/EditorHint"/></em> <$button type="set" set="$:/ShowEditPreview" setTo="yes">show preview</$button>
|
||||
<$edit field="text" class="tw-edit-texteditor" placeholder=<<prompt>>/>
|
||||
</$reveal>
|
||||
|
||||
@@ -9,6 +9,6 @@ tags: $:/tags/EditTemplate
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tw-edit-field-add">//Add a new field:// <span class="tw-edit-field-add-name"><$edit-text tiddler="$:/NewFieldName" tag="input" default="" placeholder="field name" class="tw-edit-texteditor"/></span> <span class="tw-edit-field-add-button"><$button message="tw-add-field" param={{$:/NewFieldName}} set="$:/NewFieldName" setTo="" class="">add</$button></span></div>
|
||||
<div class="tw-edit-field-add"><em class="tw-edit">Add a new field:</em> <span class="tw-edit-field-add-name"><$edit-text tiddler="$:/NewFieldName" tag="input" default="" placeholder="field name" class="tw-edit-texteditor"/></span> <span class="tw-edit-field-add-button"><$button message="tw-add-field" param={{$:/NewFieldName}} set="$:/NewFieldName" setTo="" class="">add</$button></span></div>
|
||||
|
||||
</$fieldmangler>
|
||||
|
||||
@@ -4,7 +4,7 @@ tags: $:/tags/EditTemplate
|
||||
\define tag-styles()
|
||||
background-color:$(backgroundColor)$;
|
||||
\end
|
||||
<div class="tw-edit-tags"><$fieldmangler><$list filter="[is[current]tags[]sort[title]]" storyview="pop" itemClass="tw-tag-editor-label"><$set name="backgroundColor" value={{!!color}}><span style=<<tag-styles>> class="tw-tag-label"><$view field="title" format="text" /><$button message="tw-remove-tag" param={{!!title}} class="btn-invisible tw-remove-tag-button">×</$button></span></$set>
|
||||
<div class="tw-edit-tags"><$fieldmangler><$list filter="[is[current]tags[]sort[title]]" storyview="pop"><$set name="backgroundColor" value={{!!color}}><span style=<<tag-styles>> class="tw-tag-label"><$view field="title" format="text" /><$button message="tw-remove-tag" param={{!!title}} class="btn-invisible tw-remove-tag-button">×</$button></span></$set>
|
||||
</$list>
|
||||
|
||||
<div class="tw-edit-add-tag"><span class="tw-add-tag-name"><$edit-text tiddler="$:/NewTagName" tag="input" default="" placeholder="tag name" focusPopup=<<qualify "$:/state/tagsAutoComplete">> class="tw-edit-texteditor"/></span> <$button popup=<<qualify "$:/state/tagsAutoComplete">> class="btn-invisible btn-dropdown">{{$:/core/images/down-arrow}}</$button> <span class="tw-add-tag-button"><$button message="tw-add-tag" param={{$:/NewTagName}} set="$:/NewTagName" setTo="" class="">add</$button></span></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
title: $:/core/ui/EditTemplate/type
|
||||
tags: $:/tags/EditTemplate
|
||||
|
||||
<p>//Type:// <$edit-text field="type" tag="input" default="" placeholder="type" focusPopup=<<qualify "$:/state/typeDropdown">> class="tw-edit-typeeditor"/> <$button popup=<<qualify "$:/state/typeDropdown">> class="btn-invisible btn-dropdown">{{$:/core/images/down-arrow}}</$button></p>
|
||||
<p><$fieldmangler><em class="tw-edit">Type:</em> <$edit-text field="type" tag="input" default="" placeholder="type" focusPopup=<<qualify "$:/state/typeDropdown">> class="tw-edit-typeeditor"/> <$button popup=<<qualify "$:/state/typeDropdown">> class="btn-invisible btn-dropdown">{{$:/core/images/down-arrow}}</$button> <$button message="tw-remove-field" param="type" class="btn-invisible btn-icon">{{$:/core/images/delete-button}}</$button></$fieldmangler></p>
|
||||
|
||||
<div class="tw-block-dropdown-wrapper">
|
||||
<$reveal state=<<qualify "$:/state/typeDropdown">> type="nomatch" text="" default="">
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/All
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: All
|
||||
|
||||
<$list filter="[!is[system]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$list filter="[!is[system]sort[title]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/Drafts
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: Drafts
|
||||
|
||||
<$list filter="[has[draft.of]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$list filter="[has[draft.of]sort[title]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/Missing
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: Missing
|
||||
|
||||
<$list filter="[is[missing]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/MissingTemplate"/>
|
||||
<$list filter="[is[missing]sort[title]]" template="$:/core/ui/MissingTemplate"/>
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/Orphans
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: Orphans
|
||||
|
||||
<$list filter="[is[orphan]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$list filter="[is[orphan]sort[title]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/Shadows
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: Shadows
|
||||
|
||||
<$list filter="[is[shadow]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$list filter="[is[shadow]sort[title]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
@@ -2,4 +2,4 @@ title: $:/core/ui/MoreSideBar/System
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: System
|
||||
|
||||
<$list filter="[is[system]sort[title]]" itemClass="tw-menu-list-item" template="$:/core/ui/ListItemTemplate"/>
|
||||
<$list filter="[is[system]sort[title]]" template="$:/core/ui/ListItemTemplate"/>
|
||||
|
||||
@@ -2,7 +2,7 @@ title: $:/core/ui/MoreSideBar/Tags
|
||||
tags: $:/tags/MoreSideBar
|
||||
caption: Tags
|
||||
|
||||
<$list filter="[tags[]sort[title]]" itemClass="tw-menu-list-item">
|
||||
<$list filter="[tags[]sort[title]]">
|
||||
<$transclude tiddler="$:/core/ui/TagTemplate"/> <small class="tw-menu-list-count"><$count filter="[is[current]tagging[]]"/></small>
|
||||
</$list>
|
||||
----
|
||||
|
||||
@@ -13,5 +13,21 @@ title: $:/core/ui/PageMacros
|
||||
</$reveal>
|
||||
</$list>
|
||||
</div>
|
||||
\end
|
||||
\define wikitext-example(src)
|
||||
```
|
||||
$src$
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
$src$
|
||||
|
||||
In HTML:
|
||||
|
||||
$$$text/vnd.tiddlywiki>text/html
|
||||
$src$
|
||||
$$$
|
||||
|
||||
\end
|
||||
{{$:/core/ui/PageTemplate}}
|
||||
|
||||
5
core/ui/PageStylesheet.tid
Normal file
5
core/ui/PageStylesheet.tid
Normal file
@@ -0,0 +1,5 @@
|
||||
title: $:/core/ui/PageStylesheet
|
||||
|
||||
<$list filter="[is[shadow]tag[$:/tags/stylesheet]] [!is[shadow]tag[$:/tags/stylesheet]]">
|
||||
<$transclude/>
|
||||
</$list>
|
||||
@@ -6,7 +6,7 @@ tags: $:/tags/PageTemplate
|
||||
<div class="tw-subtitle">{{SiteSubtitle}}</div>
|
||||
|
||||
<div class="tw-page-controls">
|
||||
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/PageControls]] [!is[shadow]!has[draft.of]tag[$:/tags/PageControls]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
|
||||
<$list filter="[is[shadow]!has[draft.of]tag[$:/tags/PageControls]] [!is[shadow]!has[draft.of]tag[$:/tags/PageControls]] +[tag[$:/tags/PageControls]]" variable="listItem"><$transclude tiddler=<<listItem>>/></$list>
|
||||
</div>
|
||||
|
||||
{{$:/core/ui/SideBarLists}}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user