mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-25 12:23:42 +00:00
Compare commits
562 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 | ||
|
|
28d6627632 | ||
|
|
91f10af53f | ||
|
|
ba796c3f23 | ||
|
|
64ff422c80 | ||
|
|
6c6f53a69f | ||
|
|
7fcf52543f | ||
|
|
933c61e611 | ||
|
|
da613f7dee | ||
|
|
2db3043d6e | ||
|
|
208c64aa9d | ||
|
|
2c9152fa56 | ||
|
|
3da17c8e04 | ||
|
|
fe19909034 | ||
|
|
6ee0e07036 | ||
|
|
8a2b3bc831 | ||
|
|
7baf8431a4 | ||
|
|
4352e81b98 | ||
|
|
a651c2cb72 | ||
|
|
2261fd4b84 | ||
|
|
717f959c04 | ||
|
|
3e1899ee17 | ||
|
|
7d12d89a0a | ||
|
|
c0a6e94b21 | ||
|
|
1e14ba48f9 | ||
|
|
b8f15feca4 | ||
|
|
b77aa3908f | ||
|
|
2c1ed36a91 | ||
|
|
5b89eca5e9 | ||
|
|
0956ae10a0 | ||
|
|
7175f1cbf1 | ||
|
|
384ab80c42 | ||
|
|
f534d98e8b | ||
|
|
3a9dc1a36d | ||
|
|
f9ef7b783b | ||
|
|
65a2ae8428 | ||
|
|
5ce112d431 | ||
|
|
9d60cb50ed | ||
|
|
584043deee | ||
|
|
c4a85e3b82 | ||
|
|
1b54313615 | ||
|
|
42fce1929c | ||
|
|
d96f85ac83 | ||
|
|
e3c770ca4a | ||
|
|
d7454b100a | ||
|
|
ee9cf60aa2 | ||
|
|
3a446dc240 | ||
|
|
8cf2b06e53 | ||
|
|
0184375ad1 | ||
|
|
b805633dc9 | ||
|
|
638a774fc9 | ||
|
|
b33a3293fe | ||
|
|
802fe9beae | ||
|
|
78f56ba875 | ||
|
|
c29975f6b3 | ||
|
|
ce03690989 | ||
|
|
b1c6f2d1c3 | ||
|
|
f380d4b27d | ||
|
|
f19da7af8c | ||
|
|
0013f3a31c | ||
|
|
a45f64e738 | ||
|
|
a29c0dfce9 | ||
|
|
c4e6c91986 | ||
|
|
03a81bd8b1 | ||
|
|
6945283fec | ||
|
|
113b48d046 | ||
|
|
cc9c6e4f42 | ||
|
|
97feef8909 | ||
|
|
db4f38c75b | ||
|
|
99852c3cab | ||
|
|
b6cb879ad1 | ||
|
|
f9fbbc12a6 | ||
|
|
59bb3c66d6 | ||
|
|
dc9ec22156 | ||
|
|
b8875e126f | ||
|
|
26ed978cf9 | ||
|
|
bd511cb9f3 | ||
|
|
20ea6433e6 | ||
|
|
16444e023a | ||
|
|
9c579e3596 | ||
|
|
4710431e6b | ||
|
|
f1e909278c | ||
|
|
8d3613e8b4 | ||
|
|
3fd3e408fc | ||
|
|
a2fcc59648 | ||
|
|
223e9c4747 | ||
|
|
b63f7a7416 | ||
|
|
905d3e6e1e | ||
|
|
90a0eca2f5 | ||
|
|
7658789971 | ||
|
|
9257c8205f | ||
|
|
b117f74666 | ||
|
|
3b35d7dfe4 | ||
|
|
29c0f7156b | ||
|
|
0d2ed8f112 | ||
|
|
99a6b1bcc0 | ||
|
|
da4cdf2d3b | ||
|
|
26cc62cff7 | ||
|
|
b1992714ed | ||
|
|
ecca7a3ea9 | ||
|
|
4b84d9bfe5 | ||
|
|
92b1932fcf | ||
|
|
9a6e404215 | ||
|
|
939ad11eae | ||
|
|
6785c49734 | ||
|
|
45c51481de | ||
|
|
874bd7b2b8 | ||
|
|
fc6dd83f2f | ||
|
|
a8129874fb | ||
|
|
c7d5905242 | ||
|
|
02d3620d93 | ||
|
|
b304e3fe40 | ||
|
|
06a66cf24e | ||
|
|
145e3ece78 | ||
|
|
24e361da77 | ||
|
|
1b9614eb9d | ||
|
|
791033d751 | ||
|
|
9748709759 | ||
|
|
b885743efe | ||
|
|
8ec92405fd | ||
|
|
e68ab95ecb | ||
|
|
d2dbc73448 | ||
|
|
4a5a8dd773 | ||
|
|
439dfcb172 | ||
|
|
f6a4ea6b0f | ||
|
|
8681e0228d | ||
|
|
c1123cb3e9 | ||
|
|
d64590a12b | ||
|
|
e274a0c7d1 | ||
|
|
51fe1e20e8 | ||
|
|
9c4ffae1b3 | ||
|
|
3d0c6cf41e | ||
|
|
3800d3b2b1 | ||
|
|
da54236f5a | ||
|
|
c930d84d01 | ||
|
|
2317f779e9 | ||
|
|
c501e70512 | ||
|
|
8357d90e59 | ||
|
|
efef6261b8 | ||
|
|
95b7a5d4fe | ||
|
|
2c55c7ca82 | ||
|
|
02dda51269 | ||
|
|
083cb848f2 | ||
|
|
254da0b170 | ||
|
|
8b0b9eafb8 | ||
|
|
04e2f18ff1 | ||
|
|
a4783a2c19 | ||
|
|
8fb6f26729 | ||
|
|
0e7ffa677a | ||
|
|
a668f09522 | ||
|
|
2598e22422 | ||
|
|
dc6a9c6348 | ||
|
|
b1667259f0 | ||
|
|
c77b451863 | ||
|
|
9e48460940 | ||
|
|
5e743262d4 |
32
2bld.cmd
Normal file
32
2bld.cmd
Normal file
@@ -0,0 +1,32 @@
|
||||
@echo off
|
||||
|
||||
rem build TiddlyWiki 2.x
|
||||
|
||||
rem create a temporary directory if it doesn't already exist
|
||||
setlocal enableextensions
|
||||
mkdir tmp\tw2
|
||||
setlocal disableextensions
|
||||
|
||||
rem Delete any existing content
|
||||
|
||||
del /q /s tmp\tw2
|
||||
echo.
|
||||
|
||||
rem Prepare the readme file from the revelant content in the tw5.com wiki
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
editions\tw5.com ^
|
||||
--verbose ^
|
||||
--rendertiddler TiddlyWiki2ReadMe editions\tw2\readme.md text/html ^
|
||||
|| exit 1
|
||||
|
||||
rem cook the TiddlyWiki 2.x.x index file
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
editions\tw2 ^
|
||||
--verbose ^
|
||||
--load editions\tw2\source\tiddlywiki.com\index.html.recipe ^
|
||||
--rendertiddler $:/core/templates/tiddlywiki2.template.html .\tmp\tw2\index.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
fc tmp\tw2\index.html editions\tw2\target\prebuilt.html
|
||||
107
bld.cmd
Normal file
107
bld.cmd
Normal file
@@ -0,0 +1,107 @@
|
||||
@echo off
|
||||
|
||||
rem build TiddlyWiki5 for tiddlywiki.com
|
||||
|
||||
rem Set up the build output directory
|
||||
|
||||
if "x%TW5_BUILD_OUTPUT%" == "x" (
|
||||
set TW5_BUILD_OUTPUT=..\jermolene.github.com
|
||||
)
|
||||
|
||||
if not exist %TW5_BUILD_OUTPUT%\nul (
|
||||
echo A valid TW5_BUILD_OUTPUT environment variable must be set
|
||||
exit 1
|
||||
)
|
||||
|
||||
echo Using TW5_BUILD_OUTPUT as %TW5_BUILD_OUTPUT%
|
||||
echo.
|
||||
|
||||
rem Create the `static` directories if necessary
|
||||
|
||||
setlocal enableextensions
|
||||
mkdir %TW5_BUILD_OUTPUT%\static
|
||||
setlocal disableextensions
|
||||
|
||||
rem Delete any existing content
|
||||
|
||||
del /q /s %TW5_BUILD_OUTPUT%\static
|
||||
|
||||
rem The tw5.com wiki
|
||||
rem index.html: the main file, including content
|
||||
rem empty.html: the main file, excluding content
|
||||
rem static.html: the static version of the default tiddlers
|
||||
|
||||
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
|
||||
|
||||
rem encrypted.html: a version of the main file encrypted with the password "password"
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\tw5.com ^
|
||||
--verbose ^
|
||||
--password password ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\encrypted.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
rem tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\tahoelafs ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\tahoelafs.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
rem d3demo.html: wiki to demo d3 plugin
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\d3demo ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\d3demo.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
rem codemirrordemo.html: wiki to demo codemirror plugin
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\codemirrordemo ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\codemirrordemo.html text/plain ^
|
||||
|| exit 1
|
||||
|
||||
rem markdowndemo.html: wiki to demo markdown plugin
|
||||
|
||||
node .\tiddlywiki.js ^
|
||||
.\editions\markdowndemo ^
|
||||
--verbose ^
|
||||
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\markdowndemo.html text/plain ^
|
||||
|| 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 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
|
||||
|
||||
.\test.cmd
|
||||
56
bld.sh
56
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,9 +17,9 @@ 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` directory if necessary
|
||||
# Create the `static` directories if necessary
|
||||
|
||||
mkdir -p $TW5_BUILD_OUTPUT/static
|
||||
|
||||
@@ -27,71 +27,77 @@ mkdir -p $TW5_BUILD_OUTPUT/static
|
||||
|
||||
rm $TW5_BUILD_OUTPUT/static/*
|
||||
|
||||
# First,
|
||||
# readme.md: the readme file for GitHub
|
||||
# The tw5.com wiki
|
||||
# index.html: the main file, including content
|
||||
# empty.html: the main file, excluding content
|
||||
# static.html: the static version of the default tiddlers
|
||||
|
||||
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/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/index.html text/plain \
|
||||
--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
|
||||
|
||||
# Second, encrypted.html: a version of the main file encrypted with the password "password"
|
||||
# encrypted.html: a version of the main file encrypted with the password "password"
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/tw5.com \
|
||||
--verbose \
|
||||
--password password \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/encrypted.html text/plain \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/encrypted.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Third, empty.html: empty wiki for reuse
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/empty \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/empty.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Fourth, tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
|
||||
# tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/tahoelafs \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/tahoelafs.html text/plain \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/tahoelafs.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Fifth, d3demo.html: wiki to demo d3 plugin
|
||||
# d3demo.html: wiki to demo d3 plugin
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/d3demo \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/d3demo.html text/plain \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/d3demo.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Sixth, codemirrordemo.html: wiki to demo codemirror plugin
|
||||
# codemirrordemo.html: wiki to demo codemirror plugin
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/codemirrordemo \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/codemirrordemo.html text/plain \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/codemirrordemo.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Seventh, codemirrordemo.html: wiki to demo codemirror plugin
|
||||
# markdowndemo.html: wiki to demo markdown plugin
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/markdowndemo \
|
||||
--verbose \
|
||||
--rendertiddler $:/core/templates/tiddlywiki5.template.html $TW5_BUILD_OUTPUT/markdowndemo.html text/plain \
|
||||
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/markdowndemo.html text/plain \
|
||||
|| exit 1
|
||||
|
||||
# Eighth, run the test edition to run the node.js tests and to generate test.html for tests in the browser
|
||||
# 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%;
|
||||
}
|
||||
|
||||
217
boot/boot.js
217
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,"&");
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -225,17 +216,18 @@ $tw.utils.pad = function(value,length) {
|
||||
return s;
|
||||
};
|
||||
|
||||
// Convert a date into UTC YYYYMMDDHHMM format
|
||||
// Convert a date into UTC YYYYMMDDHHMMSSmmm format
|
||||
$tw.utils.stringifyDate = function(value) {
|
||||
return value.getUTCFullYear() +
|
||||
$tw.utils.pad(value.getUTCMonth() + 1) +
|
||||
$tw.utils.pad(value.getUTCDate()) +
|
||||
$tw.utils.pad(value.getUTCHours()) +
|
||||
$tw.utils.pad(value.getUTCMinutes()) +
|
||||
$tw.utils.pad(value.getUTCSeconds()) +
|
||||
$tw.utils.pad(value.getUTCMilliseconds(),3);
|
||||
};
|
||||
|
||||
// Parse a date from a UTC YYYYMMDDHHMMSSMMM format string
|
||||
// Parse a date from a UTC YYYYMMDDHHMMSSmmm format string
|
||||
$tw.utils.parseDate = function(value) {
|
||||
if(typeof value === "string") {
|
||||
return new Date(Date.UTC(parseInt(value.substr(0,4),10),
|
||||
@@ -245,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;
|
||||
@@ -268,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 {
|
||||
@@ -281,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;
|
||||
@@ -343,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);
|
||||
@@ -426,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) {
|
||||
@@ -443,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,
|
||||
@@ -470,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) {
|
||||
@@ -498,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;
|
||||
@@ -516,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);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -554,6 +589,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
|
||||
clearInterval: clearInterval,
|
||||
setTimeout: setTimeout,
|
||||
clearTimeout: clearTimeout,
|
||||
Buffer: $tw.browser ? {} : Buffer,
|
||||
$tw: $tw,
|
||||
require: function(title) {
|
||||
return $tw.modules.execute(title, name);
|
||||
@@ -756,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) {
|
||||
@@ -836,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})
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -888,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;
|
||||
@@ -1073,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",
|
||||
@@ -1108,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:}
|
||||
*/
|
||||
@@ -1129,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);
|
||||
@@ -1175,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);
|
||||
@@ -1196,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1209,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 {
|
||||
@@ -1223,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
|
||||
@@ -1230,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);
|
||||
@@ -1311,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);
|
||||
@@ -1324,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
|
||||
@@ -1348,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
|
||||
@@ -1367,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);
|
||||
@@ -1388,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();
|
||||
@@ -1397,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();
|
||||
@@ -1406,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) {
|
||||
@@ -1427,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/application_json.tid
Normal file
3
core/docs/types/application_json.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/application/json
|
||||
description: JSON data
|
||||
name: application/json
|
||||
3
core/docs/types/application_x_tiddler_dictionary.tid
Normal file
3
core/docs/types/application_x_tiddler_dictionary.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/application/x-tiddler-dictionary
|
||||
description: Data dictionary
|
||||
name: application/x-tiddler-dictionary
|
||||
3
core/docs/types/image_gif.tid
Normal file
3
core/docs/types/image_gif.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/image/gif
|
||||
description: GIF image
|
||||
name: image/gif
|
||||
3
core/docs/types/image_jpeg.tid
Normal file
3
core/docs/types/image_jpeg.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/image/jpeg
|
||||
description: JPEG image
|
||||
name: image/jpeg
|
||||
3
core/docs/types/image_png.tid
Normal file
3
core/docs/types/image_png.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/image/png
|
||||
description: PNG image
|
||||
name: image/png
|
||||
3
core/docs/types/image_svg_xml.tid
Normal file
3
core/docs/types/image_svg_xml.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/image/svg+xml
|
||||
description: Structured Vector Graphics image
|
||||
name: image/svg+xml
|
||||
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
|
||||
3
core/docs/types/text_plain.tid
Normal file
3
core/docs/types/text_plain.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/text/plain
|
||||
description: Plain text
|
||||
name: text/plain
|
||||
3
core/docs/types/text_vnd.tiddlywiki.tid
Normal file
3
core/docs/types/text_vnd.tiddlywiki.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/docs/types/text/vnd.tiddlywiki
|
||||
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
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/cancel-button
|
||||
|
||||
<svg class="tw-image-cancel-button" viewBox="366 150 58 58" width="22pt" height="22pt"><path d="M 414.76236 158.98764 C 403.77887 148.0041 385.97113 148.0041 374.98764 158.98764 C 364.0041 169.97113 364.0041 187.77887 374.98764 198.76236 C 385.97113 209.7459 403.77887 209.7459 414.76236 198.76236 C 425.7459 187.77887 425.7459 169.97113 414.76236 158.98764 M 385.3967 165.32954 L 385.3967 165.32954 L 394.77674 174.7096 L 404.3533 165.13303 C 405.53068 163.95566 407.4396 163.95566 408.61697 165.13303 C 409.79434 166.31041 409.79434 168.21932 408.61697 169.39669 L 399.0404 178.97325 L 408.42046 188.35331 C 409.59783 189.53068 409.59783 191.43959 408.42046 192.61697 L 408.42046 192.61697 C 407.24308 193.79434 405.33417 193.79434 404.1568 192.61697 L 394.77675 183.23692 L 385.5932 192.42046 C 384.41583 193.59783 382.50692 193.59783 381.32954 192.42046 L 381.32954 192.42046 C 380.15217 191.24308 380.15217 189.33417 381.32954 188.1568 C 381.32954 188.1568 381.32954 188.1568 381.32954 188.1568 L 381.32954 188.1568 L 381.32954 188.1568 L 390.51309 178.97326 L 381.13303 169.5932 C 379.95566 168.41583 379.95566 166.50692 381.13303 165.32954 L 381.13303 165.32954 C 382.3104 164.15217 384.21932 164.15217 385.3967 165.32954 C 385.3967 165.32954 385.3967 165.32954 385.3967 165.32954 Z"/></svg>
|
||||
<svg class="tw-image-cancel-button tw-image-button" viewBox="366 150 58 58" width="22pt" height="22pt"><path d="M 414.76236 158.98764 C 403.77887 148.0041 385.97113 148.0041 374.98764 158.98764 C 364.0041 169.97113 364.0041 187.77887 374.98764 198.76236 C 385.97113 209.7459 403.77887 209.7459 414.76236 198.76236 C 425.7459 187.77887 425.7459 169.97113 414.76236 158.98764 M 385.3967 165.32954 L 385.3967 165.32954 L 394.77674 174.7096 L 404.3533 165.13303 C 405.53068 163.95566 407.4396 163.95566 408.61697 165.13303 C 409.79434 166.31041 409.79434 168.21932 408.61697 169.39669 L 399.0404 178.97325 L 408.42046 188.35331 C 409.59783 189.53068 409.59783 191.43959 408.42046 192.61697 L 408.42046 192.61697 C 407.24308 193.79434 405.33417 193.79434 404.1568 192.61697 L 394.77675 183.23692 L 385.5932 192.42046 C 384.41583 193.59783 382.50692 193.59783 381.32954 192.42046 L 381.32954 192.42046 C 380.15217 191.24308 380.15217 189.33417 381.32954 188.1568 C 381.32954 188.1568 381.32954 188.1568 381.32954 188.1568 L 381.32954 188.1568 L 381.32954 188.1568 L 390.51309 178.97326 L 381.13303 169.5932 C 379.95566 168.41583 379.95566 166.50692 381.13303 165.32954 L 381.13303 165.32954 C 382.3104 164.15217 384.21932 164.15217 385.3967 165.32954 C 385.3967 165.32954 385.3967 165.32954 385.3967 165.32954 Z"/></svg>
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/close-button
|
||||
|
||||
<svg class="tw-image-close-button" viewBox="222 150 56 56" width="22pt" height="22pt"><path d="M 249.56668 185.88827 L 267.06757 203.38916 C 269.26427 205.58586 272.82582 205.58586 275.02252 203.38916 L 275.02252 203.38916 C 277.21922 201.19246 277.21922 197.63091 275.02252 195.43421 L 257.52163 177.93332 L 275.38916 160.06579 C 277.58586 157.86909 277.58586 154.30754 275.38916 152.11084 C 273.19246 149.91414 269.63091 149.91414 267.43421 152.11084 L 249.56668 169.97837 L 232.06579 152.47748 L 232.06579 152.47748 C 232.06579 152.47748 232.06579 152.47748 232.06579 152.47748 C 229.86909 150.28078 226.30754 150.28078 224.11084 152.47748 L 224.11084 152.47748 C 221.91414 154.674175 221.91414 158.23573 224.11084 160.43243 L 241.61173 177.93332 L 224.47748 195.06757 L 224.47748 195.06757 L 224.47748 195.06757 C 224.47748 195.06757 224.47748 195.06757 224.47748 195.06757 C 222.28078 197.26427 222.28078 200.82583 224.47748 203.02252 L 224.47748 203.02252 C 226.67418 205.21922 230.23573 205.21922 232.43243 203.02252 Z"/></svg>
|
||||
<svg class="tw-image-close-button tw-image-button" viewBox="222 150 56 56" width="22pt" height="22pt"><path d="M 249.56668 185.88827 L 267.06757 203.38916 C 269.26427 205.58586 272.82582 205.58586 275.02252 203.38916 L 275.02252 203.38916 C 277.21922 201.19246 277.21922 197.63091 275.02252 195.43421 L 257.52163 177.93332 L 275.38916 160.06579 C 277.58586 157.86909 277.58586 154.30754 275.38916 152.11084 C 273.19246 149.91414 269.63091 149.91414 267.43421 152.11084 L 249.56668 169.97837 L 232.06579 152.47748 L 232.06579 152.47748 C 232.06579 152.47748 232.06579 152.47748 232.06579 152.47748 C 229.86909 150.28078 226.30754 150.28078 224.11084 152.47748 L 224.11084 152.47748 C 221.91414 154.674175 221.91414 158.23573 224.11084 160.43243 L 241.61173 177.93332 L 224.47748 195.06757 L 224.47748 195.06757 L 224.47748 195.06757 C 224.47748 195.06757 224.47748 195.06757 224.47748 195.06757 C 222.28078 197.26427 222.28078 200.82583 224.47748 203.02252 L 224.47748 203.02252 C 226.67418 205.21922 230.23573 205.21922 232.43243 203.02252 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/delete-button
|
||||
|
||||
<svg class="tw-image-delete-button" viewBox="303 155 39 50" width="17pt" height="22pt"><path d="M 333 164.25 L 333 157.25 C 333 156.14543 332.10457 155.25 331 155.25 L 314.75 155.25 C 314.75 155.25 314.75 155.25 314.75 155.25 C 313.64543 155.25 312.75 156.14543 312.75 157.25 L 312.75 164.25 L 303.75 164.25 L 303.75 168.75 L 306 168.75 L 306 201.75 L 306 201.75 L 306 201.75 C 306 203.40685 307.34315 204.75 309 204.75 L 336.75 204.75 C 338.40685 204.75 339.75 203.40685 339.75 201.75 L 339.75 168.75 L 342 168.75 L 342 164.25 Z M 317.25 160.75 L 317.25 160.75 C 317.25 160.19772 317.69772 159.75 318.25 159.75 C 318.25 159.75 318.25 159.75 318.25 159.75 L 327.5 159.75 C 328.05228 159.75 328.5 160.19772 328.5 160.75 L 328.5 164.25 L 317.25 164.25 L 317.25 160.75 Z M 310.5 168.75 L 312.75 168.75 L 312.75 200.25 L 310.5 200.25 Z M 317.25 168.75 L 319.5 168.75 L 319.5 200.25 L 317.25 200.25 Z M 324 168.75 L 326.25 168.75 L 326.25 200.25 L 324 200.25 Z M 330.75 168.75 L 333 168.75 L 333 200.25 L 330.75 200.25 Z"/></svg>
|
||||
<svg class="tw-image-delete-button tw-image-button" viewBox="303 155 39 50" width="17pt" height="22pt"><path d="M 333 164.25 L 333 157.25 C 333 156.14543 332.10457 155.25 331 155.25 L 314.75 155.25 C 314.75 155.25 314.75 155.25 314.75 155.25 C 313.64543 155.25 312.75 156.14543 312.75 157.25 L 312.75 164.25 L 303.75 164.25 L 303.75 168.75 L 306 168.75 L 306 201.75 L 306 201.75 L 306 201.75 C 306 203.40685 307.34315 204.75 309 204.75 L 336.75 204.75 C 338.40685 204.75 339.75 203.40685 339.75 201.75 L 339.75 168.75 L 342 168.75 L 342 164.25 Z M 317.25 160.75 L 317.25 160.75 C 317.25 160.19772 317.69772 159.75 318.25 159.75 C 318.25 159.75 318.25 159.75 318.25 159.75 L 327.5 159.75 C 328.05228 159.75 328.5 160.19772 328.5 160.75 L 328.5 164.25 L 317.25 164.25 L 317.25 160.75 Z M 310.5 168.75 L 312.75 168.75 L 312.75 200.25 L 310.5 200.25 Z M 317.25 168.75 L 319.5 168.75 L 319.5 200.25 L 317.25 200.25 Z M 324 168.75 L 326.25 168.75 L 326.25 200.25 L 324 200.25 Z M 330.75 168.75 L 333 168.75 L 333 200.25 L 330.75 200.25 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/done-button
|
||||
|
||||
<svg class="tw-image-done-button" viewBox="434 150 68 55" width="22pt" height="18pt"><path d="M 438.49266 178.00797 L 439.00744 177.49319 C 441.35054 175.15008 445.14946 175.15004 447.49262 177.49309 L 452.50734 182.50757 C 454.8505 184.85063 458.6494 184.85058 460.99252 182.50748 L 488.50747 154.99255 C 490.85058 152.64944 494.6495 152.6494 496.99266 154.99246 L 497.50722 155.506995 C 499.8504 157.85009 499.8505 161.64908 497.5074 163.99228 C 497.50738 163.99229 497.50736 163.99231 497.50734 163.99233 L 460.9926 200.5077 C 458.64947 202.85087 454.85048 202.8509 452.50732 200.50778 C 452.5073 200.50777 452.5073 200.50777 452.5073 200.50776 L 438.49268 186.49327 C 436.14952 184.15013 436.1495 180.35114 438.49264 178.00799 C 438.49265 178.00798 438.49265 178.00797 438.49266 178.00797 Z"/></svg>
|
||||
<svg class="tw-image-done-button tw-image-button" viewBox="434 150 68 55" width="22pt" height="18pt"><path d="M 438.49266 178.00797 L 439.00744 177.49319 C 441.35054 175.15008 445.14946 175.15004 447.49262 177.49309 L 452.50734 182.50757 C 454.8505 184.85063 458.6494 184.85058 460.99252 182.50748 L 488.50747 154.99255 C 490.85058 152.64944 494.6495 152.6494 496.99266 154.99246 L 497.50722 155.506995 C 499.8504 157.85009 499.8505 161.64908 497.5074 163.99228 C 497.50738 163.99229 497.50736 163.99231 497.50734 163.99233 L 460.9926 200.5077 C 458.64947 202.85087 454.85048 202.8509 452.50732 200.50778 C 452.5073 200.50777 452.5073 200.50777 452.5073 200.50776 L 438.49268 186.49327 C 436.14952 184.15013 436.1495 180.35114 438.49264 178.00799 C 438.49265 178.00798 438.49265 178.00797 438.49266 178.00797 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/down-arrow
|
||||
|
||||
<svg class="tw-image-down-arrow" viewBox="441 306 59 45" width="24pt" height="22pt"><path d="M 441 306 L 470.25 351 L 499.5 306 Z"/></svg>
|
||||
<svg class="tw-image-down-arrow tw-image-button" viewBox="441 306 59 45" width="24pt" height="22pt"><path d="M 441 306 L 470.25 351 L 499.5 306 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/edit-button
|
||||
|
||||
<svg class="tw-image-edit-button" viewBox="244 193 20 22" width="20pt" height="22pt"><path d="M 257.33334 196.80951 L 245.90476 207.2857 L 244 212.0476 L 248.7619 210.14284 L 260.19048 199.66665 Z M 259.2381 194.90475 L 258.28566 195.85716 L 261.14284 198.71428 L 262.09522 197.76187 Z M 261.14286 193 L 260.19042 193.95241 L 263.04762 196.80953 L 264 195.85714 Z M 244 213.72882 C 244 213.72882 247.4281 215.43353 250.8572 213.7288 C 254.28599 212.02405 261.14284 214.86531 261.14284 214.86531 L 261.14284 213.72884 C 261.14284 213.72884 254.28577 210.88755 250.8572 212.5923 C 247.42858 214.29712 244 212.59228 244 212.59228 Z"/></svg>
|
||||
<svg class="tw-image-edit-button tw-image-button" viewBox="244 193 20 22" width="20pt" height="22pt"><path d="M 257.33334 196.80951 L 245.90476 207.2857 L 244 212.0476 L 248.7619 210.14284 L 260.19048 199.66665 Z M 259.2381 194.90475 L 258.28566 195.85716 L 261.14284 198.71428 L 262.09522 197.76187 Z M 261.14286 193 L 260.19042 193.95241 L 263.04762 196.80953 L 264 195.85714 Z M 244 213.72882 C 244 213.72882 247.4281 215.43353 250.8572 213.7288 C 254.28599 212.02405 261.14284 214.86531 261.14284 214.86531 L 261.14284 213.72884 C 261.14284 213.72884 254.28577 210.88755 250.8572 212.5923 C 247.42858 214.29712 244 212.59228 244 212.59228 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/info-button
|
||||
|
||||
<svg class="tw-image-info-button" viewBox="294 150 58 58" width="22pt" height="22pt"><path d="M 342.76236 158.98764 C 331.77887 148.0041 313.97113 148.0041 302.98764 158.98764 C 292.0041 169.97113 292.0041 187.77887 302.98764 198.76236 C 313.97113 209.7459 331.77887 209.7459 342.76236 198.76236 C 353.7459 187.77887 353.7459 169.97113 342.76236 158.98764 M 326.5425 157.5 L 326.5425 157.5 C 327.72545 157.5 328.72201 157.91022 329.5337 158.73088 C 330.34465 159.55157 330.75 160.54402 330.75 161.7075 C 330.75 162.87172 330.33979 163.86316 329.51911 164.68385 C 328.69842 165.5045 327.70674 165.91501 326.5425 165.91501 C 325.39801 165.91501 324.4153 165.5045 323.5946 164.68385 C 322.77393 163.86316 322.36372 162.87172 322.36372 161.7075 C 322.36372 160.54402 322.76906 159.55157 323.58 158.73088 C 324.39171 157.91022 325.3793 157.5 326.5425 157.5 Z M 327.80211 190.47259 C 324.91945 195.49132 321.85778 198 318.61462 198 C 317.37452 198 316.38691 197.65158 315.65186 196.9555 C 314.9176 196.25866 314.54943 195.37617 314.54943 194.30782 C 314.54943 193.60202 314.71223 192.70572 315.03629 191.61813 L 319.0151 177.93651 C 319.39685 176.61922 319.58735 175.62754 319.58735 174.95991 C 319.58735 174.53996 319.40582 174.16692 319.04356 173.84286 C 318.68052 173.51905 318.18469 173.35701 317.55527 173.35701 C 317.26861 173.35701 316.92506 173.36677 316.5246 173.38548 L 316.89661 172.2407 L 326.59967 170.66627 L 328.31744 170.66627 L 322.44986 191.01638 C 322.12503 192.18064 321.963 192.94337 321.963 193.30666 C 321.963 193.51588 322.04862 193.71121 322.2204 193.89273 C 322.39218 194.07425 322.5737 194.16554 322.7642 194.16477 C 323.08903 194.16554 323.4131 194.02221 323.73792 193.73559 C 324.59605 193.02976 325.6267 191.75142 326.82838 189.90008 Z"/></svg>
|
||||
<svg class="tw-image-info-button tw-image-button" viewBox="294 150 58 58" width="22pt" height="22pt"><path d="M 342.76236 158.98764 C 331.77887 148.0041 313.97113 148.0041 302.98764 158.98764 C 292.0041 169.97113 292.0041 187.77887 302.98764 198.76236 C 313.97113 209.7459 331.77887 209.7459 342.76236 198.76236 C 353.7459 187.77887 353.7459 169.97113 342.76236 158.98764 M 326.5425 157.5 L 326.5425 157.5 C 327.72545 157.5 328.72201 157.91022 329.5337 158.73088 C 330.34465 159.55157 330.75 160.54402 330.75 161.7075 C 330.75 162.87172 330.33979 163.86316 329.51911 164.68385 C 328.69842 165.5045 327.70674 165.91501 326.5425 165.91501 C 325.39801 165.91501 324.4153 165.5045 323.5946 164.68385 C 322.77393 163.86316 322.36372 162.87172 322.36372 161.7075 C 322.36372 160.54402 322.76906 159.55157 323.58 158.73088 C 324.39171 157.91022 325.3793 157.5 326.5425 157.5 Z M 327.80211 190.47259 C 324.91945 195.49132 321.85778 198 318.61462 198 C 317.37452 198 316.38691 197.65158 315.65186 196.9555 C 314.9176 196.25866 314.54943 195.37617 314.54943 194.30782 C 314.54943 193.60202 314.71223 192.70572 315.03629 191.61813 L 319.0151 177.93651 C 319.39685 176.61922 319.58735 175.62754 319.58735 174.95991 C 319.58735 174.53996 319.40582 174.16692 319.04356 173.84286 C 318.68052 173.51905 318.18469 173.35701 317.55527 173.35701 C 317.26861 173.35701 316.92506 173.36677 316.5246 173.38548 L 316.89661 172.2407 L 326.59967 170.66627 L 328.31744 170.66627 L 322.44986 191.01638 C 322.12503 192.18064 321.963 192.94337 321.963 193.30666 C 321.963 193.51588 322.04862 193.71121 322.2204 193.89273 C 322.39218 194.07425 322.5737 194.16554 322.7642 194.16477 C 323.08903 194.16554 323.4131 194.02221 323.73792 193.73559 C 324.59605 193.02976 325.6267 191.75142 326.82838 189.90008 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/new-button
|
||||
|
||||
<svg class="tw-image-new-button" viewBox="83 81 50 50" width="22pt" height="22pt"><path d="M 101.25 112.5 L 101.25 127.5 C 101.25 127.5 101.25 127.5 101.25 127.5 L 101.25 127.5 C 101.25 129.156855 102.593146 130.5 104.25 130.5 L 111.75 130.5 C 113.406854 130.5 114.75 129.156854 114.75 127.5 L 114.75 112.5 L 129.75 112.5 C 131.406854 112.5 132.75 111.156854 132.75 109.5 L 132.75 102 C 132.75 100.343146 131.406854 99 129.75 99 L 114.75 99 L 114.75 84 C 114.75 82.343146 113.406854 81 111.75 81 L 104.25 81 C 104.25 81 104.25 81 104.25 81 C 102.593146 81 101.25 82.343146 101.25 84 L 101.25 99 L 86.25 99 C 86.25 99 86.25 99 86.25 99 C 84.593146 99 83.25 100.343146 83.25 102 L 83.25 109.5 C 83.25 109.5 83.25 109.5 83.25 109.5 L 83.25 109.5 C 83.25 111.156855 84.593146 112.5 86.25 112.5 Z"/></svg>
|
||||
<svg class="tw-image-new-button tw-image-button" viewBox="83 81 50 50" width="22pt" height="22pt"><path d="M 101.25 112.5 L 101.25 127.5 C 101.25 127.5 101.25 127.5 101.25 127.5 L 101.25 127.5 C 101.25 129.156855 102.593146 130.5 104.25 130.5 L 111.75 130.5 C 113.406854 130.5 114.75 129.156854 114.75 127.5 L 114.75 112.5 L 129.75 112.5 C 131.406854 112.5 132.75 111.156854 132.75 109.5 L 132.75 102 C 132.75 100.343146 131.406854 99 129.75 99 L 114.75 99 L 114.75 84 C 114.75 82.343146 113.406854 81 111.75 81 L 104.25 81 C 104.25 81 104.25 81 104.25 81 C 102.593146 81 101.25 82.343146 101.25 84 L 101.25 99 L 86.25 99 C 86.25 99 86.25 99 86.25 99 C 84.593146 99 83.25 100.343146 83.25 102 L 83.25 109.5 C 83.25 109.5 83.25 109.5 83.25 109.5 L 83.25 109.5 C 83.25 111.156855 84.593146 112.5 86.25 112.5 Z"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/options-button
|
||||
|
||||
<svg class="tw-image-options-button" viewBox="434 218 68 68" width="22pt" height="22pt"><path d="M 478.39696 232.53705 L 478.39696 232.53705 C 477.11453 231.85132 475.77877 231.30146 474.4106 230.88735 L 474.4106 218.24993 L 461.58944 218.24993 L 461.58944 230.88735 C 460.22126 231.30146 458.8855 231.85132 457.60308 232.53705 L 448.66825 223.60214 L 439.6022 232.66814 L 448.53716 241.60304 C 447.8515 242.88541 447.30158 244.22116 446.88747 245.58935 L 434.25 245.58935 L 434.25 258.41052 L 446.88747 258.41052 C 447.30158 259.7787 447.8515 261.11446 448.53716 262.39689 L 439.6022 271.33173 L 448.66825 280.39779 L 457.60308 271.46281 C 458.8855 272.14862 460.22126 272.69847 461.58944 273.11251 L 461.58944 285.74986 L 474.4106 285.74986 L 474.4106 273.11251 C 475.77877 272.69847 477.11453 272.14862 478.39696 271.46281 L 487.3318 280.39779 L 496.3977 271.33173 L 487.46287 262.39689 C 488.14854 261.11446 488.6984 259.7787 489.11257 258.41052 L 501.7499 258.41052 L 501.7499 245.58935 L 489.11257 245.58935 C 488.6984 244.22116 488.14854 242.88541 487.46287 241.60304 L 496.3977 232.66814 L 487.3318 223.60214 Z M 475.3328 244.66714 C 479.38253 248.71698 479.38253 255.2829 475.3328 259.33273 C 471.28297 263.3826 464.71706 263.3826 460.66723 259.33273 C 456.61737 255.2829 456.61737 248.71698 460.66723 244.66714 C 464.71706 240.61734 471.28297 240.61734 475.3328 244.66714"/></svg>
|
||||
<svg class="tw-image-options-button tw-image-button" viewBox="434 218 68 68" width="22pt" height="22pt"><path d="M 478.39696 232.53705 L 478.39696 232.53705 C 477.11453 231.85132 475.77877 231.30146 474.4106 230.88735 L 474.4106 218.24993 L 461.58944 218.24993 L 461.58944 230.88735 C 460.22126 231.30146 458.8855 231.85132 457.60308 232.53705 L 448.66825 223.60214 L 439.6022 232.66814 L 448.53716 241.60304 C 447.8515 242.88541 447.30158 244.22116 446.88747 245.58935 L 434.25 245.58935 L 434.25 258.41052 L 446.88747 258.41052 C 447.30158 259.7787 447.8515 261.11446 448.53716 262.39689 L 439.6022 271.33173 L 448.66825 280.39779 L 457.60308 271.46281 C 458.8855 272.14862 460.22126 272.69847 461.58944 273.11251 L 461.58944 285.74986 L 474.4106 285.74986 L 474.4106 273.11251 C 475.77877 272.69847 477.11453 272.14862 478.39696 271.46281 L 487.3318 280.39779 L 496.3977 271.33173 L 487.46287 262.39689 C 488.14854 261.11446 488.6984 259.7787 489.11257 258.41052 L 501.7499 258.41052 L 501.7499 245.58935 L 489.11257 245.58935 C 488.6984 244.22116 488.14854 242.88541 487.46287 241.60304 L 496.3977 232.66814 L 487.3318 223.60214 Z M 475.3328 244.66714 C 479.38253 248.71698 479.38253 255.2829 475.3328 259.33273 C 471.28297 263.3826 464.71706 263.3826 460.66723 259.33273 C 456.61737 255.2829 456.61737 248.71698 460.66723 244.66714 C 464.71706 240.61734 471.28297 240.61734 475.3328 244.66714"/></svg>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
title: $:/core/images/save-button
|
||||
|
||||
<svg class="tw-image-save-button" viewBox="4 512 64 60" width="22pt" height="21pt"><path d="M 13.5 537.75 L 11.5 537.75 C 11.5 537.75 11.5 537.75 11.5 537.75 C 7.6340064 537.75 4.4999994 540.884 4.5 544.75 L 4.5 564.5 L 4.5 564.5 C 4.5 564.5 4.5 564.5 4.5 564.5 L 4.5 564.5 C 4.5000006 568.366 7.634007 571.5 11.5 571.5 L 60.5 571.5 C 64.365993 571.5 67.5 568.366 67.5 564.5 L 67.5 544.75 C 67.5 540.884 64.365993 537.75 60.5 537.75 L 58.5 537.75 L 49.5 546.75 L 50 546.75 C 52.20914 546.75 54 548.54086 54 550.75 L 54 556.25 C 54 558.45914 52.20914 560.25 50 560.25 L 36 560.25 L 22 560.25 C 19.790861 560.25 18 558.45914 18 556.25 L 18 556.25 C 18 556.25 18 556.25 18 556.25 L 18 550.75 C 18 548.54086 19.790861 546.75 22 546.75 C 22 546.75 22 546.75 22 546.75 L 22.5 546.75 Z"/><path d="M 16.37132 533.87132 L 33.87868 551.37868 C 35.050253 552.55025 36.949747 552.55025 38.12132 551.37868 L 55.62868 533.87132 C 56.800252 532.69975 56.800252 530.80025 55.62868 529.62868 C 55.06607 529.06607 54.30301 528.75 53.50736 528.75 L 48 528.75 C 46.343146 528.75 45 527.40685 45 525.75 L 45 516 C 45 514.34315 43.656854 513 42 513 L 30 513 C 28.343146 513 27 514.34315 27 516 L 27 525.75 C 27 527.40685 25.656854 528.75 24 528.75 L 18.492641 528.75 C 16.835786 528.75 15.492641 530.09315 15.492641 531.75 C 15.492641 532.54565 15.808711 533.3087 16.37132 533.87132 Z"/></svg>
|
||||
<svg class="tw-image-save-button tw-image-button" viewBox="4 512 64 60" width="22pt" height="21pt"><path d="M 13.5 537.75 L 11.5 537.75 C 11.5 537.75 11.5 537.75 11.5 537.75 C 7.6340064 537.75 4.4999994 540.884 4.5 544.75 L 4.5 564.5 L 4.5 564.5 C 4.5 564.5 4.5 564.5 4.5 564.5 L 4.5 564.5 C 4.5000006 568.366 7.634007 571.5 11.5 571.5 L 60.5 571.5 C 64.365993 571.5 67.5 568.366 67.5 564.5 L 67.5 544.75 C 67.5 540.884 64.365993 537.75 60.5 537.75 L 58.5 537.75 L 49.5 546.75 L 50 546.75 C 52.20914 546.75 54 548.54086 54 550.75 L 54 556.25 C 54 558.45914 52.20914 560.25 50 560.25 L 36 560.25 L 22 560.25 C 19.790861 560.25 18 558.45914 18 556.25 L 18 556.25 C 18 556.25 18 556.25 18 556.25 L 18 550.75 C 18 548.54086 19.790861 546.75 22 546.75 C 22 546.75 22 546.75 22 546.75 L 22.5 546.75 Z"/><path d="M 16.37132 533.87132 L 33.87868 551.37868 C 35.050253 552.55025 36.949747 552.55025 38.12132 551.37868 L 55.62868 533.87132 C 56.800252 532.69975 56.800252 530.80025 55.62868 529.62868 C 55.06607 529.06607 54.30301 528.75 53.50736 528.75 L 48 528.75 C 46.343146 528.75 45 527.40685 45 525.75 L 45 516 C 45 514.34315 43.656854 513 42 513 L 30 513 C 28.343146 513 27 514.34315 27 516 L 27 525.75 C 27 527.40685 25.656854 528.75 24 528.75 L 18.492641 528.75 C 16.835786 528.75 15.492641 530.09315 15.492641 531.75 C 15.492641 532.54565 15.808711 533.3087 16.37132 533.87132 Z"/></svg>
|
||||
|
||||
3
core/messages/StartingSave.tid
Normal file
3
core/messages/StartingSave.tid
Normal file
@@ -0,0 +1,3 @@
|
||||
title: $:/messages/StartingSave
|
||||
|
||||
Starting to save wiki
|
||||
@@ -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;
|
||||
|
||||
})();
|
||||
@@ -49,27 +49,57 @@ SimpleServer.prototype.addRoute = function(route) {
|
||||
this.routes.push(route);
|
||||
};
|
||||
|
||||
SimpleServer.prototype.listen = function(port) {
|
||||
SimpleServer.prototype.findMatchingRoute = function(request,state) {
|
||||
for(var t=0; t<this.routes.length; t++) {
|
||||
var potentialRoute = this.routes[t],
|
||||
pathRegExp = potentialRoute.path,
|
||||
match = potentialRoute.path.exec(state.urlInfo.pathname);
|
||||
if(match && request.method === potentialRoute.method) {
|
||||
state.params = [];
|
||||
for(var p=1; p<match.length; p++) {
|
||||
state.params.push(match[p]);
|
||||
}
|
||||
return potentialRoute;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
SimpleServer.prototype.checkCredentials = function(request,incomingUsername,incomingPassword) {
|
||||
var header = request.headers["authorization"] || "",
|
||||
token = header.split(/\s+/).pop() || "",
|
||||
auth = $tw.utils.base64Decode(token),
|
||||
parts = auth.split(/:/),
|
||||
username = parts[0],
|
||||
password = parts[1];
|
||||
if(incomingUsername === username && incomingPassword === password) {
|
||||
return "ALLOWED";
|
||||
} else {
|
||||
return "DENIED";
|
||||
}
|
||||
}
|
||||
|
||||
SimpleServer.prototype.listen = function(port,host) {
|
||||
var self = this;
|
||||
http.createServer(function(request, response) {
|
||||
http.createServer(function(request,response) {
|
||||
// Compose the state object
|
||||
var state = {};
|
||||
state.wiki = self.wiki;
|
||||
state.server = self;
|
||||
state.urlInfo = url.parse(request.url);
|
||||
// Find the route that matches this path
|
||||
var route;
|
||||
for(var t=0; t<self.routes.length; t++) {
|
||||
var potentialRoute = self.routes[t],
|
||||
pathRegExp = potentialRoute.path,
|
||||
match = potentialRoute.path.exec(state.urlInfo.pathname);
|
||||
if(request.method === potentialRoute.method && match) {
|
||||
state.params = [];
|
||||
for(var p=1; p<match.length; p++) {
|
||||
state.params.push(match[p]);
|
||||
}
|
||||
route = potentialRoute;
|
||||
break;
|
||||
var route = self.findMatchingRoute(request,state);
|
||||
// Check for the username and password if we've got one
|
||||
var username = self.get("username"),
|
||||
password = self.get("password");
|
||||
if(username && password) {
|
||||
// Check they match
|
||||
if(self.checkCredentials(request,username,password) !== "ALLOWED") {
|
||||
response.writeHead(401,"Authentication required",{
|
||||
"WWW-Authenticate": 'Basic realm="Please provide your username and password to login to TiddlyWiki5"'
|
||||
});
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Return a 404 if we didn't find a route
|
||||
@@ -95,7 +125,7 @@ SimpleServer.prototype.listen = function(port) {
|
||||
});
|
||||
break;
|
||||
}
|
||||
}).listen(port);
|
||||
}).listen(port,host);
|
||||
};
|
||||
|
||||
var Command = function(params,commander,callback) {
|
||||
@@ -166,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") {
|
||||
@@ -221,20 +260,22 @@ var Command = function(params,commander,callback) {
|
||||
|
||||
Command.prototype.execute = function() {
|
||||
var port = this.params[0] || "8080",
|
||||
rootTiddler = this.params[1] || "$:/core/templates/tiddlywiki5.template.html",
|
||||
rootTiddler = this.params[1] || "$:/core/save/all",
|
||||
renderType = this.params[2] || "text/plain",
|
||||
serveType = this.params[3] || "text/html",
|
||||
username = this.params[4] || "ANONYMOUS";
|
||||
username = this.params[4],
|
||||
password = this.params[5],
|
||||
host = this.params[6] || "127.0.0.1";
|
||||
this.server.set({
|
||||
rootTiddler: rootTiddler,
|
||||
renderType: renderType,
|
||||
serveType: serveType,
|
||||
username: username
|
||||
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) !== "]");
|
||||
@@ -131,7 +155,14 @@ exports.filterTiddlers = function(filterString,currTiddlerTitle,tiddlerList) {
|
||||
};
|
||||
|
||||
exports.compileFilter = function(filterString) {
|
||||
var filterParseTree = this.parseFilter(filterString);
|
||||
var filterParseTree;
|
||||
try {
|
||||
filterParseTree = this.parseFilter(filterString);
|
||||
} catch(e) {
|
||||
return function(source,currTiddlerTitle) {
|
||||
return ["Filter error: " + e];
|
||||
};
|
||||
}
|
||||
// Get the hashmap of filter operator functions
|
||||
var filterOperators = this.getFilterOperators();
|
||||
// Assemble array of functions, one for each operation
|
||||
@@ -154,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;
|
||||
}
|
||||
|
||||
43
core/modules/filters/is/tiddler.js
Normal file
43
core/modules/filters/is/tiddler.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/is/tiddler.js
|
||||
type: application/javascript
|
||||
module-type: isfilteroperator
|
||||
|
||||
Filter function for [is[tiddler]]
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.tiddler = function(source,prefix,options) {
|
||||
var results = [];
|
||||
// Function to check a tiddler
|
||||
function checkTiddler(title) {
|
||||
var match = options.wiki.tiddlerExists(title);
|
||||
if(prefix === "!") {
|
||||
match = !match;
|
||||
}
|
||||
if(match) {
|
||||
results.push(title);
|
||||
}
|
||||
};
|
||||
// Iterate through the source tiddlers
|
||||
if($tw.utils.isArray(source)) {
|
||||
$tw.utils.each(source,function(title) {
|
||||
checkTiddler(title);
|
||||
});
|
||||
} else {
|
||||
$tw.utils.each(source,function(element,title) {
|
||||
checkTiddler(title);
|
||||
});
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -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) {
|
||||
|
||||
@@ -22,7 +22,7 @@ exports.types = {block: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /<<([^\s>]+)\s*([\s\S]*?)>>(?:\r?\n|$)/mg;
|
||||
this.matchRegExp = /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\r?\n|$)/mg;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
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;
|
||||
|
||||
@@ -7,10 +7,7 @@ Wiki text rule for block-level transclusion. For example:
|
||||
|
||||
```
|
||||
{{MyTiddler}}
|
||||
{{MyTiddler|tooltip}}
|
||||
{{MyTiddler||TemplateTitle}}
|
||||
{{MyTiddler|tooltip||TemplateTitle}}
|
||||
{{MyTiddler}width:40;height:50;}.class.class
|
||||
```
|
||||
|
||||
\*/
|
||||
@@ -26,7 +23,7 @@ exports.types = {block: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /\{\{([^\{\}\|]+)(?:\|([^\|\{\}]+))?(?:\|\|([^\|\{\}]+))?\}([^\}]*)\}(?:\.(\S+))?(?:\r?\n|$)/mg;
|
||||
this.matchRegExp = /\{\{([^\{\}\|]+)(?:\|\|([^\|\{\}]+))?\}\}(?:\r?\n|$)/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
@@ -38,17 +35,12 @@ exports.parse = function() {
|
||||
targetTitle = tr.title,
|
||||
targetField = tr.field,
|
||||
targetIndex = tr.index,
|
||||
tooltip = this.match[2],
|
||||
template = $tw.utils.trim(this.match[3]),
|
||||
style = this.match[4],
|
||||
classes = this.match[5];
|
||||
template = $tw.utils.trim(this.match[2]);
|
||||
// Prepare the transclude widget
|
||||
var transcludeNode = {
|
||||
type: "element",
|
||||
tag: "$transclude",
|
||||
attributes: {
|
||||
tiddler: {type: "string", value: template || targetTitle}
|
||||
},
|
||||
attributes: {},
|
||||
isBlock: true
|
||||
};
|
||||
var tiddlerNode = {
|
||||
@@ -60,20 +52,16 @@ exports.parse = function() {
|
||||
isBlock: true,
|
||||
children: [transcludeNode]
|
||||
};
|
||||
if(targetField) {
|
||||
transcludeNode.attributes.field = {type: "string", value: targetField};
|
||||
}
|
||||
if(targetIndex) {
|
||||
transcludeNode.attributes.index = {type: "string", value: targetIndex};
|
||||
}
|
||||
if(tooltip) {
|
||||
transcludeNode.attributes.tooltip = {type: "string", value: tooltip};
|
||||
}
|
||||
if(style) {
|
||||
transcludeNode.attributes.style = {type: "string", value: style};
|
||||
}
|
||||
if(classes) {
|
||||
transcludeNode.attributes["class"] = {type: "string", value: classes.split(".").join(" ")};
|
||||
if(template) {
|
||||
transcludeNode.attributes.tiddler = {type: "string", value: template};
|
||||
} else {
|
||||
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
|
||||
if(targetField) {
|
||||
transcludeNode.attributes.field = {type: "string", value: targetField};
|
||||
}
|
||||
if(targetIndex) {
|
||||
transcludeNode.attributes.index = {type: "string", value: targetIndex};
|
||||
}
|
||||
}
|
||||
return [tiddlerNode];
|
||||
};
|
||||
|
||||
@@ -7,10 +7,7 @@ Wiki text rule for inline-level transclusion. For example:
|
||||
|
||||
```
|
||||
{{MyTiddler}}
|
||||
{{MyTiddler|tooltip}}
|
||||
{{MyTiddler||TemplateTitle}}
|
||||
{{MyTiddler|tooltip||TemplateTitle}}
|
||||
{{MyTiddler}width:40;height:50;}.class.class
|
||||
```
|
||||
|
||||
\*/
|
||||
@@ -26,7 +23,7 @@ exports.types = {inline: true};
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
// Regexp to match
|
||||
this.matchRegExp = /\{\{([^\{\}\|]+)(?:\|([^\|\{\}]+))?(?:\|\|([^\|\{\}]+))?\}([^\}]*)\}(?:\.(\S+))?/mg;
|
||||
this.matchRegExp = /\{\{([^\{\}\|]+)(?:\|\|([^\|\{\}]+))?\}\}/mg;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
@@ -38,17 +35,12 @@ exports.parse = function() {
|
||||
targetTitle = tr.title,
|
||||
targetField = tr.field,
|
||||
targetIndex = tr.index,
|
||||
tooltip = this.match[2],
|
||||
template = $tw.utils.trim(this.match[3]),
|
||||
style = this.match[4],
|
||||
classes = this.match[5];
|
||||
template = $tw.utils.trim(this.match[2]);
|
||||
// Prepare the transclude widget
|
||||
var transcludeNode = {
|
||||
type: "element",
|
||||
tag: "$transclude",
|
||||
attributes: {
|
||||
tiddler: {type: "string", value: template || targetTitle}
|
||||
}
|
||||
attributes: {}
|
||||
};
|
||||
var tiddlerNode = {
|
||||
type: "element",
|
||||
@@ -58,20 +50,16 @@ exports.parse = function() {
|
||||
},
|
||||
children: [transcludeNode]
|
||||
};
|
||||
if(targetField) {
|
||||
transcludeNode.attributes.field = {type: "string", value: targetField};
|
||||
}
|
||||
if(targetIndex) {
|
||||
transcludeNode.attributes.index = {type: "string", value: targetIndex};
|
||||
}
|
||||
if(tooltip) {
|
||||
transcludeNode.attributes.tooltip = {type: "string", value: tooltip};
|
||||
}
|
||||
if(style) {
|
||||
transcludeNode.attributes.style = {type: "string", value: style};
|
||||
}
|
||||
if(classes) {
|
||||
transcludeNode.attributes["class"] = {type: "string", value: classes.split(".").join(" ")};
|
||||
if(template) {
|
||||
transcludeNode.attributes.tiddler = {type: "string", value: template};
|
||||
} else {
|
||||
transcludeNode.attributes.tiddler = {type: "string", value: targetTitle};
|
||||
if(targetField) {
|
||||
transcludeNode.attributes.field = {type: "string", value: targetField};
|
||||
}
|
||||
if(targetIndex) {
|
||||
transcludeNode.attributes.index = {type: "string", value: targetIndex};
|
||||
}
|
||||
}
|
||||
return [tiddlerNode];
|
||||
};
|
||||
|
||||
@@ -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 [{
|
||||
|
||||
@@ -15,7 +15,11 @@ Handles saving changes via the AndTidWiki Android app
|
||||
var AndTidWiki = function(wiki) {
|
||||
};
|
||||
|
||||
AndTidWiki.prototype.save = function(text,callback) {
|
||||
AndTidWiki.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 = decodeURIComponent(document.location.toString());
|
||||
// Strip the file://
|
||||
|
||||
@@ -18,7 +18,7 @@ Select the appropriate saver module and set it up
|
||||
var DownloadSaver = function(wiki) {
|
||||
};
|
||||
|
||||
DownloadSaver.prototype.save = function(text) {
|
||||
DownloadSaver.prototype.save = function(text,method,callback) {
|
||||
// Get the current filename
|
||||
var filename = "tiddlywiki.html",
|
||||
p = document.location.pathname.lastIndexOf("/");
|
||||
@@ -28,7 +28,7 @@ DownloadSaver.prototype.save = function(text) {
|
||||
// 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);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -21,7 +21,7 @@ Select the appropriate saver module and set it up
|
||||
var ManualDownloadSaver = function(wiki) {
|
||||
};
|
||||
|
||||
ManualDownloadSaver.prototype.save = function(text) {
|
||||
ManualDownloadSaver.prototype.save = function(text,method,callback) {
|
||||
$tw.modal.display(downloadInstructionsTitle,{
|
||||
downloadLink: "data:text/html," + encodeURIComponent(text)
|
||||
});
|
||||
|
||||
56
core/modules/savers/msdownload.js
Normal file
56
core/modules/savers/msdownload.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/*\
|
||||
title: $:/core/modules/savers/msdownload.js
|
||||
type: application/javascript
|
||||
module-type: saver
|
||||
|
||||
Handles saving changes via window.navigator.msSaveBlob()
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Select the appropriate saver module and set it up
|
||||
*/
|
||||
var MsDownloadSaver = function(wiki) {
|
||||
};
|
||||
|
||||
MsDownloadSaver.prototype.save = function(text,method,callback) {
|
||||
// Get the current filename
|
||||
var filename = "tiddlywiki.html",
|
||||
p = document.location.pathname.lastIndexOf("/");
|
||||
if(p !== -1) {
|
||||
filename = document.location.pathname.substr(p+1);
|
||||
}
|
||||
// Set up the link
|
||||
var blob = new Blob([text], {type: "text/html"});
|
||||
window.navigator.msSaveBlob(blob,filename);
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
Information about this saver
|
||||
*/
|
||||
MsDownloadSaver.prototype.info = {
|
||||
name: "msdownload",
|
||||
priority: 110
|
||||
};
|
||||
|
||||
/*
|
||||
Static method that returns true if this saver is capable of working
|
||||
*/
|
||||
exports.canSave = function(wiki) {
|
||||
return !!window.navigator.msSaveBlob;
|
||||
};
|
||||
|
||||
/*
|
||||
Create an instance of this saver
|
||||
*/
|
||||
exports.create = function(wiki) {
|
||||
return new MsDownloadSaver(wiki);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -15,7 +15,11 @@ Handles saving changes via the TiddlyFox file extension
|
||||
var TiddlyFoxSaver = function(wiki) {
|
||||
};
|
||||
|
||||
TiddlyFoxSaver.prototype.save = function(text,callback) {
|
||||
TiddlyFoxSaver.prototype.save = function(text,method,callback) {
|
||||
// Bail out unless this is a save (rather than a download)
|
||||
if(method !== "save") {
|
||||
return false;
|
||||
}
|
||||
var messageBox = document.getElementById("tiddlyfox-message-box");
|
||||
if(messageBox) {
|
||||
// Get the pathname of this document
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -15,7 +15,11 @@ Handles saving changes via the TWEdit iOS app
|
||||
var TWEditSaver = function(wiki) {
|
||||
};
|
||||
|
||||
TWEditSaver.prototype.save = function(text,callback) {
|
||||
TWEditSaver.prototype.save = function(text,method,callback) {
|
||||
// Bail out unless this is a save (rather than a download)
|
||||
if(method !== "save") {
|
||||
return false;
|
||||
}
|
||||
// Bail if we're not running under TWEdit
|
||||
if(typeof DeviceInfo !== "object") {
|
||||
return false;
|
||||
|
||||
@@ -21,12 +21,17 @@ var UploadSaver = function(wiki) {
|
||||
this.wiki = wiki;
|
||||
};
|
||||
|
||||
UploadSaver.prototype.save = function(text) {
|
||||
UploadSaver.prototype.save = function(text,method,callback) {
|
||||
// Bail out unless this is a save (rather than a download)
|
||||
if(method !== "save") {
|
||||
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() === "") {
|
||||
@@ -43,7 +48,7 @@ UploadSaver.prototype.save = function(text) {
|
||||
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("");
|
||||
@@ -56,10 +61,15 @@ UploadSaver.prototype.save = function(text) {
|
||||
http.setRequestHeader("Content-Type","multipart/form-data; ;charset=UTF-8; boundary=" + boundary);
|
||||
http.onreadystatechange = function() {
|
||||
if(http.readyState == 4 && http.status == 200) {
|
||||
window.alert(http.responseText);
|
||||
if(http.responseText.substr(0,4) === "0 - ") {
|
||||
callback(null);
|
||||
} else {
|
||||
callback(http.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
http.send(data);
|
||||
$tw.notifier.display("$:/messages/StartingSave");
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -68,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) {
|
||||
@@ -89,14 +93,24 @@ exports.startup = function() {
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
|
||||
$tw.wiki.saveWiki({
|
||||
method: "download",
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
// Install the crypto event handlers
|
||||
$tw.rootWidget.addEventListener("tw-set-password",function(event) {
|
||||
$tw.passwordPrompt.createPrompt({
|
||||
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
|
||||
}
|
||||
});
|
||||
@@ -104,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);
|
||||
@@ -115,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/snowwhite";
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ exports.removeChildren = function(node) {
|
||||
};
|
||||
|
||||
exports.hasClass = function(el,className) {
|
||||
return el.className.split(" ").indexOf(className) !== -1;
|
||||
return el && el.className && el.className.split(" ").indexOf(className) !== -1;
|
||||
};
|
||||
|
||||
exports.addClass = function(el,className) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,16 +26,28 @@ Popup.prototype.show = function(options) {
|
||||
this.title = options.title;
|
||||
this.wiki = options.wiki;
|
||||
this.anchorDomNode = options.domNode;
|
||||
$tw.utils.addClass(this.anchorDomNode,"tw-popup");
|
||||
this.rootElement.addEventListener("click",this,false);
|
||||
};
|
||||
|
||||
Popup.prototype.handleEvent = function(event) {
|
||||
if(event.type === "click" && this.anchorDomNode !== event.target && !$tw.utils.domContains(this.anchorDomNode,event.target)) {
|
||||
this.cancel();
|
||||
// Dismiss the popup if we get a click on an element that doesn't have .tw-popup class
|
||||
if(event.type === "click") {
|
||||
var node = event.target;
|
||||
while(node && !$tw.utils.hasClass(node,"tw-popup")) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
if(!node) {
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Popup.prototype.cancel = function() {
|
||||
if(this.anchorDomNode) {
|
||||
$tw.utils.removeClass(this.anchorDomNode,"tw-popup");
|
||||
this.anchorDomNode = null;
|
||||
}
|
||||
this.rootElement.removeEventListener("click",this,false);
|
||||
if(this.title) {
|
||||
this.wiki.deleteTiddler(this.title);
|
||||
|
||||
@@ -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);
|
||||
@@ -402,4 +402,27 @@ exports.getAnimationDuration = function() {
|
||||
return parseInt($tw.wiki.getTiddlerText("$:/config/AnimationDuration","400"),10);
|
||||
};
|
||||
|
||||
/*
|
||||
Hash a string to a number
|
||||
Derived from http://stackoverflow.com/a/15710692
|
||||
*/
|
||||
exports.hashString = function(str) {
|
||||
return str.split("").reduce(function(a,b) {
|
||||
a = ((a << 5) - a) + b.charCodeAt(0);
|
||||
return a & a;
|
||||
},0);
|
||||
};
|
||||
|
||||
/*
|
||||
Decode a base64 string
|
||||
*/
|
||||
exports.base64Decode = function(string64) {
|
||||
if($tw.browser) {
|
||||
// TODO
|
||||
throw "$tw.utils.base64Decode() doesn't work in the browser";
|
||||
} else {
|
||||
return (new Buffer(string64,"base64")).toString();
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -62,7 +62,7 @@ CheckboxWidget.prototype.handleChangeEvent = function(event) {
|
||||
var checked = this.inputDomNode.checked,
|
||||
tiddler = this.wiki.getTiddler(this.checkboxTitle);
|
||||
if(tiddler && tiddler.hasTag(this.checkboxTag) !== checked) {
|
||||
var newTags = tiddler.fields.tags.slice(0),
|
||||
var newTags = (tiddler.fields.tags || []).slice(0),
|
||||
pos = newTags.indexOf(this.checkboxTag);
|
||||
if(pos !== -1) {
|
||||
newTags.splice(pos,1);
|
||||
|
||||
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.generateTitle("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}
|
||||
}
|
||||
}]);
|
||||
};
|
||||
|
||||
@@ -72,10 +72,13 @@ FieldManglerWidget.prototype.handleRemoveFieldEvent = function(event) {
|
||||
|
||||
FieldManglerWidget.prototype.handleAddFieldEvent = function(event) {
|
||||
var tiddler = this.wiki.getTiddler(this.mangleTitle);
|
||||
if(tiddler && typeof event.param === "string" && event.param !== "" && !$tw.utils.hop(tiddler.fields,event.param)) {
|
||||
var addition = {};
|
||||
addition[event.param] = "";
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
||||
if(tiddler && typeof event.param === "string") {
|
||||
var name = event.param.toLowerCase();
|
||||
if(name !== "" && !$tw.utils.hop(tiddler.fields,name)) {
|
||||
var addition = this.wiki.getModificationFields();
|
||||
addition[name] = "";
|
||||
this.wiki.addTiddler(new $tw.Tiddler(tiddler,addition));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -85,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));
|
||||
}
|
||||
}
|
||||
@@ -97,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();
|
||||
|
||||
@@ -24,6 +24,7 @@ var NavigatorWidget = function(parseTreeNode,options) {
|
||||
{type: "tw-cancel-tiddler", handler: "handleCancelTiddlerEvent"},
|
||||
{type: "tw-close-tiddler", handler: "handleCloseTiddlerEvent"},
|
||||
{type: "tw-close-all-tiddlers", handler: "handleCloseAllTiddlersEvent"},
|
||||
{type: "tw-close-other-tiddlers", handler: "handleCloseOtherTiddlersEvent"},
|
||||
{type: "tw-new-tiddler", handler: "handleNewTiddlerEvent"},
|
||||
{type: "tw-import-tiddlers", handler: "handleImportTiddlersEvent"},
|
||||
]);
|
||||
@@ -69,125 +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) {
|
||||
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);
|
||||
}
|
||||
@@ -227,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"],
|
||||
draftOf = tiddler.fields["draft.of"];
|
||||
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;
|
||||
};
|
||||
@@ -299,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
|
||||
@@ -319,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;
|
||||
};
|
||||
|
||||
@@ -342,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 {
|
||||
@@ -352,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(),
|
||||
tiddlerFields,
|
||||
self.wiki.getModificationFields(),
|
||||
{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;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ PasswordWidget.prototype.render = function(parent,nextSibling) {
|
||||
// Execute our logic
|
||||
this.execute();
|
||||
// Get the current password
|
||||
var password = $tw.browser ? $tw.utils.getPassword(this.passwordName) : "";
|
||||
var password = $tw.browser ? $tw.utils.getPassword(this.passwordName) || "" : "";
|
||||
// Create our element
|
||||
var domNode = this.document.createElement("input");
|
||||
domNode.setAttribute("type","password");
|
||||
|
||||
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;
|
||||
|
||||
})();
|
||||
@@ -38,6 +38,7 @@ RevealWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.renderChildren(domNode,null);
|
||||
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup" && this.isOpen) {
|
||||
this.positionPopup(domNode);
|
||||
$tw.utils.addClass(domNode,"tw-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
||||
}
|
||||
if(!this.isOpen) {
|
||||
domNode.setAttribute("hidden","true")
|
||||
@@ -156,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;
|
||||
@@ -179,6 +181,8 @@ RevealWidget.prototype.updateState = function() {
|
||||
// Animate our DOM node
|
||||
if(!domNode.isTiddlyWikiFakeDom && this.type === "popup" && this.isOpen) {
|
||||
this.positionPopup(domNode);
|
||||
$tw.utils.addClass(domNode,"tw-popup"); // Make sure that clicks don't dismiss popups within the revealed content
|
||||
|
||||
}
|
||||
if(this.isOpen) {
|
||||
domNode.removeAttribute("hidden");
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/setvariable.js
|
||||
title: $:/core/modules/widgets/set.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Setvariable widget
|
||||
Set variable widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
@@ -14,19 +14,19 @@ Setvariable widget
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var SetVariableWidget = function(parseTreeNode,options) {
|
||||
var SetWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
SetVariableWidget.prototype = new Widget();
|
||||
SetWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
SetVariableWidget.prototype.render = function(parent,nextSibling) {
|
||||
SetWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
@@ -36,7 +36,7 @@ SetVariableWidget.prototype.render = function(parent,nextSibling) {
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
SetVariableWidget.prototype.execute = function() {
|
||||
SetWidget.prototype.execute = function() {
|
||||
// Get our parameters
|
||||
this.setName = this.getAttribute("name","currentTiddler");
|
||||
this.setValue = this.getAttribute("value");
|
||||
@@ -49,7 +49,7 @@ SetVariableWidget.prototype.execute = function() {
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
SetVariableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
SetWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.name || changedAttributes.value) {
|
||||
this.refreshSelf();
|
||||
@@ -59,6 +59,7 @@ SetVariableWidget.prototype.refresh = function(changedTiddlers) {
|
||||
}
|
||||
};
|
||||
|
||||
exports.setvariable = SetVariableWidget;
|
||||
exports.setvariable = SetWidget;
|
||||
exports.set = SetWidget;
|
||||
|
||||
})();
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -57,6 +57,12 @@ ViewWidget.prototype.execute = function() {
|
||||
case "htmlencoded":
|
||||
this.text = this.getValueAsHtmlEncoded();
|
||||
break;
|
||||
case "urlencoded":
|
||||
this.text = this.getValueAsUrlEncoded();
|
||||
break;
|
||||
case "doubleurlencoded":
|
||||
this.text = this.getValueAsDoubleUrlEncoded();
|
||||
break;
|
||||
case "date":
|
||||
this.text = this.getValueAsDate(this.viewTemplate);
|
||||
break;
|
||||
@@ -126,20 +132,34 @@ ViewWidget.prototype.getValueAsText = function() {
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlWikified = function() {
|
||||
return this.wiki.renderText("text/html","text/vnd.tiddlywiki",this.getValueAsText(),this);
|
||||
return this.wiki.renderText("text/html","text/vnd.tiddlywiki",this.getValueAsText(),{parentWidget: this});
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsHtmlEncoded = function() {
|
||||
return $tw.utils.htmlEncode(this.getValueAsText());
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsUrlEncoded = function() {
|
||||
return encodeURIComponent(this.getValueAsText());
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsDoubleUrlEncoded = function() {
|
||||
return encodeURIComponent(encodeURIComponent(this.getValueAsText()));
|
||||
};
|
||||
|
||||
ViewWidget.prototype.getValueAsDate = function(format) {
|
||||
return $tw.utils.formatDateString(this.getValue(),format);
|
||||
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 "";
|
||||
}
|
||||
};
|
||||
|
||||
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 "";
|
||||
|
||||
@@ -38,8 +38,10 @@ Widget.prototype.initialise = function(parseTreeNode,options) {
|
||||
// Save widget info
|
||||
this.parseTreeNode = parseTreeNode;
|
||||
this.wiki = options.wiki;
|
||||
this.variables = options.variables || {};
|
||||
this.parentWidget = options.parentWidget;
|
||||
this.variablesConstructor = function() {};
|
||||
this.variablesConstructor.prototype = this.parentWidget ? this.parentWidget.variables : {};
|
||||
this.variables = new this.variablesConstructor();
|
||||
this.document = options.document;
|
||||
this.attributes = {};
|
||||
this.children = [];
|
||||
@@ -67,6 +69,16 @@ Widget.prototype.execute = function() {
|
||||
this.makeChildWidgets();
|
||||
};
|
||||
|
||||
/*
|
||||
Set the value of a context variable
|
||||
name: name of the variable
|
||||
value: value of the variable
|
||||
params: array of {name:, default:} for each parameter
|
||||
*/
|
||||
Widget.prototype.setVariable = function(name,value,params) {
|
||||
this.variables[name] = {value: value, params: params};
|
||||
};
|
||||
|
||||
/*
|
||||
Get the prevailing value of a context variable
|
||||
name: name of variable
|
||||
@@ -78,19 +90,14 @@ defaultValue: default value if the variable is not defined
|
||||
Widget.prototype.getVariable = function(name,options) {
|
||||
options = options || {};
|
||||
var actualParams = options.params || [];
|
||||
// Search up the widget tree for the variable name
|
||||
var node = this;
|
||||
while(node && !$tw.utils.hop(node.variables,name)) {
|
||||
node = node.parentWidget;
|
||||
}
|
||||
// If we get to the root then look for a macro module
|
||||
if(!node) {
|
||||
// If the variable doesn't exist then look for a macro module
|
||||
if(!(name in this.variables)) {
|
||||
return this.evaluateMacroModule(name,actualParams,options.defaultValue);
|
||||
}
|
||||
// Get the value
|
||||
var value = node.variables[name].value || "";
|
||||
var variable = this.variables[name],
|
||||
value = variable.value || "";
|
||||
// Substitute any parameters specified in the definition
|
||||
value = this.substituteVariableParameters(value,node.variables[name].params,actualParams);
|
||||
value = this.substituteVariableParameters(value,variable.params,actualParams);
|
||||
value = this.substituteVariableReferences(value);
|
||||
return value;
|
||||
};
|
||||
@@ -136,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 {
|
||||
@@ -166,16 +178,6 @@ Widget.prototype.evaluateMacroModule = function(name,actualParams,defaultValue)
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Set the value of a context variable
|
||||
name: name of the variable
|
||||
value: value of the variable
|
||||
params: array of {name:, default:} for each parameter
|
||||
*/
|
||||
Widget.prototype.setVariable = function(name,value,params) {
|
||||
this.variables[name] = {value: value, params: params};
|
||||
};
|
||||
|
||||
/*
|
||||
Check whether a given context variable value exists in the parent chain
|
||||
*/
|
||||
@@ -191,7 +193,7 @@ Widget.prototype.hasVariable = function(name,value) {
|
||||
};
|
||||
|
||||
/*
|
||||
Construct a qualifying string based on concatenating the values of a given variable in the parent chain
|
||||
Construct a qualifying string based on a hash of concatenating the values of a given variable in the parent chain
|
||||
*/
|
||||
Widget.prototype.getStateQualifier = function(name) {
|
||||
name = name || "transclusion";
|
||||
@@ -203,7 +205,7 @@ Widget.prototype.getStateQualifier = function(name) {
|
||||
}
|
||||
node = node.parentWidget;
|
||||
}
|
||||
return output.join("");
|
||||
return "{" + $tw.utils.hashString(output.join("")) + "}";
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -217,8 +219,7 @@ Widget.prototype.computeAttributes = function() {
|
||||
if(attribute.type === "indirect") {
|
||||
value = self.wiki.getTextReference(attribute.textReference,"",self.getVariable("currentTiddler"));
|
||||
} else if(attribute.type === "macro") {
|
||||
var text = self.getVariable(attribute.value.name,{params: attribute.value.params});
|
||||
value = self.wiki.renderText("text/plain","text/vnd.tiddlywiki",text);
|
||||
value = self.getVariable(attribute.value.name,{params: attribute.value.params});
|
||||
} else { // String attribute
|
||||
value = attribute.value;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user