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

Compare commits

...

367 Commits

Author SHA1 Message Date
Jermolene
0cca9092ef Version number update for 5.0.13-beta 2014-06-24 10:44:51 +01:00
Jermolene
b594eb5b36 Update release dates 2014-06-24 10:42:46 +01:00
Jermolene
917c4404e5 Update batch files to use build system 2014-06-24 10:39:45 +01:00
Jermolene
6f3e31abe5 Fixed problems with detecting changes to draft tiddlers 2014-06-23 23:28:22 +01:00
Jermolene
5962600cb6 Update release note 2014-06-23 18:13:50 +01:00
Jeremy Ruston
cf3f11a4c0 Merge pull request #669 from jayfresh/patch-1
Typo fix
2014-06-23 18:12:34 +01:00
Jeremy Ruston
bcf37c765f Merge pull request #670 from jayfresh/patch-2
Adding Jonathan Lister to individuals list
2014-06-23 18:12:02 +01:00
Jonathan Lister
248029b53a Adding Jonathan Lister to individuals list 2014-06-23 12:51:08 +01:00
Jonathan Lister
57c534b97d Typo fix 2014-06-23 12:34:05 +01:00
Jermolene
6d1eaeb0fc Fix detection of draft changes
We were getting a lot of problems where changes to a tiddler were not
being recognised
2014-06-23 08:10:32 +01:00
Jermolene
680fe41ed7 Add isEqual() method to tiddlers 2014-06-23 08:09:59 +01:00
Jermolene
32a1da7673 Fixed problem with pasted items lacking a type 2014-06-22 11:58:00 +01:00
Jermolene
8d78336e9b Docs update 2014-06-22 11:45:07 +01:00
Jermolene
9987e6de22 Fix problem with overwriting existing tiddlers 2014-06-22 11:45:00 +01:00
Jermolene
38530f14f2 Docs updates 2014-06-22 11:14:24 +01:00
Jermolene
0fae9ee992 Improve handling of popup state
An improvement to 6fb992690d

By making sure that all the popup state tiddlers have the prefix
$:/state/popup/ we can be more selective and just exclude popup state
tiddlers when we save. The end result is that once again other kinds of
state are persisted as expected (eg tabs, and sidebar visibility).
2014-06-22 11:14:11 +01:00
Jermolene
12b5ebb946 A new colour palette 2014-06-22 11:11:09 +01:00
Jeremy Ruston
5120a1b32b Merge pull request #664 from BramChen/master
Add chinese translations of the TOC tab caption
2014-06-21 20:44:14 +01:00
Jeremy Ruston
9a2d650868 Merge pull request #665 from xcazin/fr-FR
fr-FR missing captions for Sidebar
2014-06-21 20:34:15 +01:00
Jeremy Ruston
ad74877dad Merge pull request #666 from pmario/de-DE
german translations
2014-06-21 20:33:47 +01:00
Mario Pietsch
b77ad3061d german translations 2014-06-21 17:35:02 +02:00
Xavier Cazin
31b1e073a6 Missing Sidebar fr-FR caption, plus better translation for Contents 2014-06-21 17:20:01 +02:00
Xavier Cazin
5d88f19ec6 fr-FR translation for TableOfContents caption 2014-06-21 17:09:44 +02:00
Bram Chen
133c24e9c7 Add chinese translations of the TOC tab caption 2014-06-21 22:04:43 +08:00
Jermolene
f15eba66fe Use SVG icons for expand/collapse 2014-06-21 11:49:42 +01:00
Jermolene
911a64221a Docs update 2014-06-21 11:49:30 +01:00
Jermolene
424c0737a2 Update release note 2014-06-21 11:21:27 +01:00
Jermolene
0b38cd640c Reverse accidentally making Contents the default tab 2014-06-21 11:18:59 +01:00
Jermolene
32099b85d3 Add table of contents to tw5.com 2014-06-21 11:17:04 +01:00
Jermolene
71aa2bbe5f Docs update 2014-06-21 11:16:48 +01:00
Jermolene
fb5c44a875 Remove indenting
It didn’t work very well, and was giving us spans where there should be
divs in the tab control.
2014-06-21 11:16:35 +01:00
Jermolene
f12d7bb6c0 Update to version 8.0 of highlight.js 2014-06-21 10:11:04 +01:00
Jeremy Ruston
665e490d33 Merge pull request #662 from xcazin/fr-FR
fr-FR translation of new Buttons-related strings plus type editors and c...
2014-06-20 18:52:15 +01:00
Jeremy Ruston
76f637d57a Merge pull request #661 from buggyj/jsonparams2
added missing regex update for triple double-quotes macro params
2014-06-20 18:51:51 +01:00
Xavier Cazin
2ccc13b936 fr-FR translation of new Buttons-related strings plus type editors and canonical_uri related strings 2014-06-20 17:14:16 +02:00
buggyj
0206358a1c added missing regex update for triple double-quotes macro params 2014-06-19 19:17:26 +02:00
Jermolene
f3a466ee86 Docs update 2014-06-19 12:37:54 +01:00
Jeremy Ruston
0c48502e8e Merge pull request #660 from buggyj/jsonparams
added triple double-quotes delimiters for marco/widget parameters (to su...
2014-06-19 12:06:00 +01:00
Jermolene
19061650de Refactoring for hygeine 2014-06-19 12:05:41 +01:00
Jermolene
c2b08b43b5 Docs updates 2014-06-19 08:53:24 +01:00
buggyj
a2ec4c55e3 added triple double-quotes delimiters for marco/widget parameters (to support json strings) 2014-06-19 07:29:14 +02:00
Jeremy Ruston
5eae2f0fb6 Merge pull request #659 from BramChen/master
Update chinese translations
2014-06-18 14:57:30 +01:00
Jermolene
b8aedf2ca3 Fixed problem with Markdown image handling 2014-06-18 14:56:32 +01:00
Bram Chen
2d24d05f61 Update chinese translations
* for adding editor type mappings to control panel
2014-06-18 21:47:45 +08:00
Jeremy Ruston
44cb3bc100 Merge pull request #658 from csugden/patch-1
Fixes undefined loop variables (fixes #657)
2014-06-18 13:57:54 +01:00
Jermolene
0cf4e5514c Docs tweak 2014-06-18 13:54:24 +01:00
Jermolene
1717c93d00 Refactor codemirror plugin
It no longer overrides the edit-text widget. Instead we use the editor
type mappings to select which content types should be handled by which
editor.
2014-06-18 13:54:19 +01:00
Jermolene
0bdc5b5c70 Add editor type mappings to control panel 2014-06-18 13:52:22 +01:00
csugden
1945af0b2d Fixes undefined loop variables (fixes #657) 2014-06-18 11:56:27 +01:00
Jermolene
e6b783154f Allow arbitrary fields in plugin.info files
Fixes #642
2014-06-18 08:52:31 +01:00
Jermolene
d2d0b09235 Refactoring plugin loading on Node.js 2014-06-18 08:34:49 +01:00
Jermolene
e28c2e8b06 Remove extraneous tag
Tiddlers tagged “resources” show up in the Community tiddler, which we
don’t want here.
2014-06-17 22:26:55 +01:00
Jermolene
2e2d30bae9 Docs for environment variable support
Fixes #531
2014-06-17 22:26:27 +01:00
Jermolene
a9b7df96c2 Add support for TIDDLYWIKI_EDITION_PATH 2014-06-17 21:59:20 +01:00
Jermolene
b2e48d00e9 Add environment variables for locating plugins
Start of fixing #531 (we still need to deal with
TIDDLYWIKI_EDITION_PATH)
2014-06-17 21:33:44 +01:00
Jermolene
9147cadd3c Remove the cat from the server architecture diagram 2014-06-17 16:14:00 +01:00
Jeremy Ruston
4951a53063 Merge pull request #656 from BramChen/master
Update chinese translations
2014-06-17 15:47:45 +01:00
Bram Chen
36556b817f Update chinese translations
* add Buttons.multids
* add description of _canonical_uri to filds.multids
2014-06-17 21:22:29 +08:00
Jermolene
8bd19c4e6a Merge branch 'accessibility' 2014-06-17 11:49:06 +01:00
Jermolene
34e4166dc5 Add label and title for show/hide sidebar buttons
More fixes for #650
2014-06-17 11:39:18 +01:00
Jermolene
617963bd88 Update button widget docs 2014-06-17 10:49:13 +01:00
Jermolene
346b2f8611 Add label for advanced search link 2014-06-17 07:56:36 +01:00
Jermolene
6f859c8d44 Add label for close button in open sidebar tab 2014-06-17 07:56:27 +01:00
Jermolene
325a93f3c3 Move button language to $:/language/Buttons 2014-06-17 07:56:13 +01:00
Jermolene
06b0f9adb7 Added aria-label attribute to link widget
And document it for the button widget
2014-06-17 07:54:10 +01:00
Jermolene
401349a1d6 Improve a11y of close buttons in open tab
a11y === accessibility
2014-06-16 17:40:38 +01:00
Jermolene
bc9b67cbc3 Use H1 for page title and H2 for tiddler titles
Ideally, we’d also rebase the headings within tiddlers so that `!
Heading` would be an H3. Hopefully we’ll do that later.
2014-06-16 17:34:20 +01:00
Jermolene
6fb992690d Exclude state tiddlers when saving changes
This might be a controversial change as it also means that it is no
longer possible to include `$:/state/…` tiddlers in a wiki to set up
the initial configuration.
2014-06-16 17:21:41 +01:00
Jeremy Ruston
57f3eb0b2c Merge pull request #653 from BramChen/master
Correct chinese translations of Help text for savetiddlers
2014-06-15 08:40:01 +01:00
Jermolene
bf2f88ba8b Use H1 for tiddler titles
Part of #650
2014-06-15 08:37:58 +01:00
Bram Chen
00d041b778 Correct chinese translations of Help text for savetiddlers 2014-06-15 08:17:12 +08:00
Jermolene
eeedcb6d94 First pass at accessibility improvements for #650 2014-06-14 18:06:56 +01:00
Jermolene
b4ddaccd1d Docs and image updates
These two architecture diagrams are a few hundred kilobytes, so we
don’t want them baked into the HTML file
2014-06-14 13:41:09 +01:00
Jermolene
d83c26fe3b Add external image support to tiddlywiki.com 2014-06-14 13:24:48 +01:00
Jermolene
1c484f59bd Add external image build target for empty edition 2014-06-14 13:24:27 +01:00
Jeremy Ruston
149ca0fc63 Merge pull request #651 from BramChen/master
Update chinese translations of Help text for server command
2014-06-14 08:20:09 +01:00
Jeremy Ruston
f467ae288b Merge pull request #652 from xcazin/fr-FR
fr-FR translations of recently added commands and type, plus suggestion for en-GB/Help/savetiddlers.tid
2014-06-14 08:20:02 +01:00
Jermolene
457764077b Recommitting the old tw2parser plugin 2014-06-14 08:17:16 +01:00
Xavier Cazin
892900c9c5 fr-FR translation of setfield and savetiddlers docs, plus javascript type 2014-06-14 07:40:12 +02:00
Xavier Cazin
d880cb135a Update what was left from a copy/paste of savetiddler.tid :-) 2014-06-14 07:35:53 +02:00
Bram Chen
a858329742 Update chinese translations of Help text for server command
...
2014-06-14 09:19:00 +08:00
Jermolene
e44450edc4 Correct typo 2014-06-13 17:02:39 +01:00
Jermolene
f09d69d1b7 Remove debugging code 2014-06-13 14:44:43 +01:00
Jermolene
eee3a0cf8e Extend server command to allow a path prefix
Thereby making the number of parameters to the command ludicrous
2014-06-13 14:44:34 +01:00
Jermolene
4238af2a40 Extend listed filter operator to use any field 2014-06-13 10:58:19 +01:00
Jeremy Ruston
f54f0d1c3e Merge pull request #649 from BramChen/master
Update translated group of application Javascript in type dropdown
2014-06-13 10:08:10 +01:00
Jermolene
ca34cc437c Rename $:/core/templates/canonical-uri-external-image
As per @pmario’s suggestion.
2014-06-13 10:04:31 +01:00
Bram Chen
71c886e3a1 Update translated group of application Javascript in type dropdown 2014-06-13 16:36:23 +08:00
Jeremy Ruston
db147e3673 Merge pull request #648 from BramChen/master
Update chinese translations
2014-06-13 08:51:42 +01:00
Bram Chen
525613750b Update chinese translations 2014-06-13 09:42:27 +08:00
Jermolene
f751e2ecb4 Added application JavaScript to type dropdown
Fixes #646
2014-06-12 19:12:58 +01:00
Jeremy Ruston
ea5989048c Merge pull request #640 from danielo515/patch-2
Update instructions.tid to use one of the included addons
2014-06-12 19:10:12 +01:00
Jeremy Ruston
eec849c69e Merge pull request #647 from BramChen/master
Update chinese translations for Help tiddlers
2014-06-12 19:09:36 +01:00
Jermolene
666f243a82 Release note and doc updates for 5.0.13 2014-06-12 19:03:12 +01:00
Jermolene
4e5fa2c6e6 Docs update 2014-06-12 18:01:39 +01:00
Jermolene
9ab0c84140 Support global macros via the importvariables widget
The new importvariables widget imports macro/variable definitions from
the specified tiddlers and makes them available to its children.

Allows us to split PageMacros up into separate tiddlers.

We still support loading macros from $:/core/ui/PageMacros to help
people upgrading.

Fixes #644 and #559
2014-06-12 18:01:33 +01:00
Bram Chen
9261bdaa43 Merge remote-tracking branch 'upstream/master' 2014-06-12 20:19:05 +08:00
Jermolene
0e09fbf46a Start using the build command in batch files 2014-06-12 08:36:53 +01:00
Jermolene
9547a1f01c First pass at external image support
A bunch of little changes that together enable external image support.
Try:

```
tiddlywiki editions/tw5.com --verbose --build externalimages
```

Then open `externalimages.html`, look for the images in the more/types
tab of the sidebar, open them and verify that they are set with an
external SRC attribute, not a data URI.
2014-06-12 08:36:30 +01:00
Bram Chen
0e4afc3986 Update chinese translations for Help tiddlers 2014-06-12 10:59:19 +08:00
Bram Chen
10fa72d15e Update chinese translations for Help tiddlers 2014-06-12 10:56:04 +08:00
Jermolene
f131c37893 Update HTML parser to use an IFRAME
Gives us better sandboxing of unsafe HTML content
2014-06-11 23:04:58 +01:00
Jermolene
d2796d0c9c Introduce setfield command
This new command will let us do the manipulations needed to set up
external image tiddlers
2014-06-11 10:05:35 +01:00
Jermolene
460f476aef Docs update 2014-06-10 23:15:42 +01:00
Jermolene
2989c9b133 Typo in 305617b632
Tsk
2014-06-10 23:05:08 +01:00
Jermolene
3105afe6e8 Add demo PDF image
That cat again
2014-06-10 23:03:41 +01:00
Jermolene
a03a15e7de Allow the text widget to refresh if needed 2014-06-10 19:32:55 +01:00
Jermolene
305617b632 Introduce savetiddlers command
Allows us to save tiddlers in their raw format.
2014-06-09 14:45:41 +01:00
Jermolene
b446ef5d4e Docs updates on Reporting Bugs 2014-06-09 14:16:21 +01:00
danielo515
8dd30e97ac Update instructions.tid to use one of the included addons
This addon is already included into the plugin, but is not used, neither mentioned how to use it. It is a very useful but lightweight addon. I consider it is better to include the full functionality of the current configuration in the config example.
2014-06-07 17:04:43 +02:00
Jermolene
fc6d96672d Another select widget demo 2014-06-06 09:33:24 +01:00
Jermolene
78791192c3 Style updates missed off the last commit 2014-06-06 09:32:45 +01:00
Jermolene
9b576f2a8d Add group headings to type dropdown
We’re also reverting to the old custom dropdown. Using the select
widget didn’t work out because it couldn’t cleanly work with a text box
allowing custom types to be specified.
2014-06-06 09:32:14 +01:00
Jeremy Ruston
08ed0017af Merge pull request #637 from mwfogleman/emacs-helper-functions
Add docs for open- and browse-wiki Emacs functions.
2014-06-03 23:14:11 +01:00
Michael Fogleman
450c646c31 Add docs for open- and browse-wiki Emacs functions.
These helper functions supplement tid-mode.
2014-06-03 23:04:29 +08:00
Jeremy Ruston
0c6c5002c1 Merge pull request #635 from danielo515/patch-1
Added Daniel Rodríguez to contributors list
2014-06-02 20:38:03 +01:00
danielo515
9b3b08a176 Added Daniel Rodríguez to contributors list
The date is the original when I tried to add myself at first instance.
2014-06-02 17:05:22 +02:00
Jeremy Ruston
6386bf84a5 Merge pull request #630 from xcazin/fr-FR
Add fr-FR translated groups to Tiddler types
2014-06-02 12:17:28 +01:00
Jeremy Ruston
c3dfa3f27e Merge pull request #631 from BramChen/master
Add chinese translations of 'group' field to tiddler types
2014-06-02 12:17:09 +01:00
Bram Chen
50223562ea Add chinese translations of 'group' field to tiddler types 2014-06-01 12:31:25 +08:00
Xavier Cazin
85c7da95bb Add fr-FR translated groups to Tiddler types 2014-06-01 00:38:58 +02:00
Jermolene
c8e98c1567 Use the select widget tiddler content types 2014-05-31 22:39:32 +01:00
Jermolene
13463a47c5 Attention Translators! Add "group" field to tiddler types
Apologies to the translators for the extra work. Each translated
tiddler type needs a new “group” field that contains a locale-specific
group name that in English are “Image”, “Developer” and “Text”.
2014-05-31 22:38:50 +01:00
Jermolene
ffd9df670d Fix problem with tabs switching on language change
In 5.0.12-beta, if you change the current language setting then the
current sidebar tab setting is lost. This was because the qualified
title generated for the tabs was incorporating the current language
title, by virtue of a trick used in the PageTemplate to set the
“languageTitle” variable to a field of the current language plugin.
This trick left the current tiddler set to the current language, and
this current tiddler was still in force for the transclusion of the
page template segments.
2014-05-31 19:20:51 +01:00
Jermolene
d2edd9291e Standardise whitespace 2014-05-31 19:18:46 +01:00
Jermolene
247eb04b11 Extraneous semi-colon 2014-05-31 19:18:01 +01:00
Jermolene
954946352a Docs update 2014-05-31 18:38:25 +01:00
Jermolene
0ccaedd7d2 Use the select widget in the various switchers 2014-05-31 18:38:17 +01:00
Jermolene
3182a2d599 Add first pass at select widget 2014-05-31 18:37:43 +01:00
Jermolene
f999b2e931 Add wiki.setText() method 2014-05-31 18:37:27 +01:00
Jermolene
4d70d5780e Use radio buttons in navigation settings
Radio buttons are much clearer
2014-05-31 18:36:59 +01:00
Jermolene
a330cb543e Better defaults for radio widget
Now the “field” attribute defaults to “text”.
2014-05-31 18:35:41 +01:00
Jermolene
64a6544b02 Update the first rule of TiddlyWiki 2014-05-30 11:38:42 +01:00
Jermolene
3f25db0abe More permalink tweaks
And more documentation this time!
2014-05-29 23:17:21 +01:00
Jermolene
412cde6f53 Move "storyviews" filter operator to correct folder 2014-05-28 17:17:47 +01:00
Jermolene
f7b8813a27 Change permalink behaviour
Now a link to a single tiddler like http://tiddlywiki.com/#HelloThere
will just open that single tiddler (the old behaviour was to also open
the default tiddlers)
2014-05-28 17:07:41 +01:00
Jermolene
62c602e9d2 Fix for running under node-webkit 2014-05-28 08:57:29 +01:00
Jermolene
d8a142fed5 Fix vertical tabs in Safari
Current versions of Safari on OS X and iOS are still prefixed.
2014-05-27 19:06:27 +01:00
Jermolene
1b37d660ea Restore "escape" as shortcut to abandon edits
Thus reverting a defensive change back in January:
d72d245523
2014-05-27 15:42:33 +01:00
Jermolene
da273be054 Workaround Firefox "no element found" bug
See https://bugzilla.mozilla.org/show_bug.cgi?id=884693

Fixes #468
2014-05-27 09:49:48 +01:00
Jermolene
a463859a28 Retract inadvertant change from previous commit 2014-05-26 22:56:58 +01:00
Jermolene
9aaa000d3f Fixed default tiddler not appearing in zoomin view
See https://groups.google.com/d/topic/tiddlywiki/c-z7f-h1CAo/discussion
2014-05-26 22:56:28 +01:00
Jermolene
f14ecf4eb8 Add support for $:/tags/RawMarkup 2014-05-26 22:50:54 +01:00
Jermolene
128ad01866 Fix for inability to scroll modal wizards 2014-05-26 22:33:42 +01:00
Jermolene
ecbda326cb Add keyboard shortcut documentation 2014-05-26 21:50:04 +01:00
Jeremy Ruston
e24600f9bb Merge pull request #617 from IreneKnapp/Irene-contributor
Sign the contributor agreement.
2014-05-26 19:19:01 +01:00
Jermolene
6436dc22a7 Fix obsolete transclude widget docs 2014-05-26 18:01:53 +01:00
Jermolene
f44f2b33ed Fixed missing class on external pretty links 2014-05-26 17:57:35 +01:00
Jermolene
86d182fd51 Fix importing blank fields from TiddlyWiki files 2014-05-26 17:47:07 +01:00
Jermolene
3fa4b00ede Docs update 2014-05-26 17:38:36 +01:00
Jermolene
d30cb0f11d New ribbon colour for 5.0.13 2014-05-18 20:02:21 +01:00
Jermolene
906d2db57e Preparing for 5.0.13 2014-05-18 19:58:23 +01:00
Irene Knapp
3e6de03f15 Sign the contributor agreement. 2014-05-17 11:04:46 -07:00
Jermolene
aaec1b2854 Version number update for 5.0.12-beta 2014-05-17 01:17:04 +01:00
Jermolene
9edebc78e7 Tweak ribbon colour for 5.0.12 2014-05-17 01:14:20 +01:00
Jermolene
e228ac42db Fix problem with shadow tiddler iteration
See https://groups.google.com/d/topic/tiddlywiki/pNxZsSCVp7c/discussion
for more details of the bug.
2014-05-17 01:12:08 +01:00
Jermolene
be0bc04929 Fix typo 2014-05-17 01:11:41 +01:00
Jermolene
b415b0e90e Version number update for 5.0.11-beta 2014-05-16 14:55:32 +01:00
Jermolene
974aecba1f Fix build scripts 2014-05-16 14:53:16 +01:00
Jermolene
47fa18c2e0 Docs updates 2014-05-16 14:49:28 +01:00
Jermolene
d5094463f4 Temporarily revoke sorting tests
localeCompare seems to behave differently in the browser and under
Node.js, making it hard to get the tests consistent
2014-05-16 14:46:55 +01:00
Jermolene
5951dc5901 Fix problem with static renderings
The issue was that rendertiddlers always clears the output folder,
which meant that it was overwriting anything previously output by the
rendertiddler command.
2014-05-16 14:39:24 +01:00
Jermolene
1d15e4b7d3 Docs update 2014-05-16 14:37:05 +01:00
Jeremy Ruston
67e66b4698 Merge pull request #610 from BramChen/master
Update chinese translations
2014-05-16 11:24:47 +01:00
Jeremy Ruston
c00940f2d1 Merge pull request #614 from pmario/de-DE
add transcluded lingo :)
2014-05-16 09:22:13 +01:00
Jermolene
81ea326e16 Update release note 2014-05-16 09:22:00 +01:00
Jeremy Ruston
c2f52f8a4b Merge pull request #615 from nameanyone/master
Rename some system tiddlers to be consistent with Naming of System Tiddlers
2014-05-16 09:20:32 +01:00
Jeremy Ruston
ca03984663 Merge pull request #616 from xcazin/fr-FR
fr-FR edits: integration of standard search into 'Advanced Search'.
2014-05-16 09:19:42 +01:00
Jermolene
b2ff248d07 Correct typo 2014-05-16 09:18:43 +01:00
Jermolene
658bd2b8a3 Release note update 2014-05-16 09:18:37 +01:00
Xavier Cazin
a8b16c9c07 fr-FR edits: integration of standard search into 'Advanced Search'. 2014-05-16 09:37:54 +02:00
nameanyone
157ca0c8aa Rename $:/temp/NewFieldName to $:/temp/newfieldname
As per "Naming of System Tiddlers"
2014-05-15 22:54:46 -07:00
nameanyone
01b3962b2c Rename $:/ShowEditPreview to $:/state/showeditpreview
According to "Naming of System Tiddlers"
2014-05-15 22:47:21 -07:00
Bram Chen
19646c7f95 Add chinese translations of standard search 2014-05-16 08:38:13 +08:00
Mario Pietsch
dfb8a07204 add transcluded lingo :) 2014-05-16 00:26:12 +02:00
Jermolene
93566cdc33 Add standard search to advanced search 2014-05-15 23:09:31 +01:00
Jeremy Ruston
ad8a20bfed Merge pull request #613 from pmario/de-DE
update german texts
2014-05-15 22:49:17 +01:00
Jeremy Ruston
00cddd3713 Merge pull request #612 from xcazin/fr-FR
Edits to fr-FR strings to reflect fix in Advanced Search matches count
2014-05-15 22:48:50 +01:00
Mario Pietsch
23c8902e70 update german texts 2014-05-15 22:58:29 +02:00
Xavier Cazin
818fd598dc Edits to fr-FR strings to reflect fix in Advanced Search matches count 2014-05-15 22:37:33 +02:00
Jermolene
31e1088aa7 Clean up startup logging
Now we do boot logging to an array. We harvest it in the —verbose
command. We still need to provide a way to access the log in the
browser too.
2014-05-15 18:50:14 +01:00
Jermolene
f9f8ad725b Fix problem with advanced search counts
Apologies to TiddlyWiki’s translators for disrupting existing work!
2014-05-14 20:12:38 +01:00
Jermolene
81e1af1d35 Tabs appearance tweaks 2014-05-14 19:37:37 +01:00
Jermolene
c9c1b0fbb4 Get rid of the tweakParseTreeNode() hack
It’s an embarrassing hangover from a refactoring of the parsing
mechanism last year.
2014-05-14 08:51:08 +01:00
Bram Chen
f7ce0c0b8d Add chinese translations of Advanced Settings in the ControlPanel 2014-05-14 09:38:45 +08:00
Jermolene
92aa1f24be Fix tab button padding
Lack of padding caused a visual glitch in Firefox
2014-05-13 21:02:21 +01:00
Jermolene
e0a6c4e879 Update release note 2014-05-13 19:38:39 +01:00
Jermolene
f72c177ba5 Fix line height 2014-05-13 18:32:12 +01:00
Jermolene
9a26c4259a Fix problem with widget.getStateQualifier()
Fixed to take into account the recent change to read variables from the
parent widget: e60fc9f81f
2014-05-13 18:16:45 +01:00
Jeremy Ruston
6de6a43623 Merge pull request #609 from xcazin/fr-FR
fr-FR translations for new strings in the Control Panel, plus edits to an older one
2014-05-13 17:33:46 +01:00
Xavier Cazin
2fa3c8a4ed edits to the fr-FR translation for the Edit Template 2014-05-13 17:28:45 +02:00
Xavier Cazin
295094c9a3 fr-FR translation of Advanced Settings in the ControlPanel 2014-05-13 17:27:22 +02:00
Jermolene
da41879fc1 Fix dropdown behaviour in advanced settings 2014-05-13 16:21:01 +01:00
Jermolene
f8708874bc Update reveal widget docs 2014-05-13 14:50:45 +01:00
Jermolene
ad43958571 Make permalink behaviour configurable
In the process introducing a new advanced settings tab

Fixes #600
2014-05-13 14:16:58 +01:00
Jermolene
4e07b3335b Extend .tid files to allow single line text fields
To make it easier to create tiddlers that don’t include a terminating
newline in their text
2014-05-13 10:27:03 +01:00
Jermolene
b77d5f9725 Clean up whitespace 2014-05-13 10:26:02 +01:00
Jermolene
75fee26b58 Fix problem with variables containing an empty string
See
https://github.com/Jermolene/TiddlyWiki5/commit/e60fc9f81f2c8f0d115543d8
d330a1d68f9b890a#commitcomment-6301921
2014-05-13 10:15:55 +01:00
Jermolene
e8c9d78079 Update release note 2014-05-12 15:21:59 +01:00
Jermolene
d972988a53 Remove obsolete filter operators docs
It was overwritten by a later version in editions/tw5.com/filters.
2014-05-12 15:17:16 +01:00
Jermolene
e83759e86d Add "before" and "after" filter operators
Fixes #357 by adding new “before” and “after” filter operators.
2014-05-12 15:16:44 +01:00
Jermolene
2633247492 Use flexbox for vertical tabs
Thus stepping into a new world:

http://caniuse.com/flexbox

The vertical tabs are now completely reusable, with sensible wrapping
behaviour.
2014-05-12 08:41:47 +01:00
Jermolene
b3032d452f Refactor vertical tabs for reusability
In practice, if you look at TabsMacro you’ll see that the width of the
tab content is wrong, and will usually overflow the container. Next
step is to fix that by using flexbox…
2014-05-11 18:47:14 +01:00
Jermolene
e60fc9f81f Fixed problem with widgets variable access
Previously, widgets were reading variables from themselves or their
cascaded ancestors. That means that if a widget sets a variable and
then reads the same variable, it will get the same variable back. That
sounds reasonable, until you consider a widget that wants to modify a
variable - eg the tiddler macro. For example:

```
<$tiddler tiddler={{!!report}}>
<$transclude mode="block" />
</$tiddler>
```

Here we first evaluate the `{{!!report}}` reference, which involves
reading the currentTiddler variable, looking up the tiddler, and
retrieving it’s `report` field. The next the tiddler widget is
refreshed, it will use the newly set currentTiddler as the basis for
resolving the `{{!!reference}}` reference.

The fix is to get variables from ancestors, but continue to set them on
ourselves.
2014-05-08 11:51:02 +01:00
Jermolene
6ab68e0fca Remove erroneous global wiki references
$tw.wiki is used as a global reference in the outer initialisation
modules. It shouldn’t be used in widgets etc.
2014-05-07 14:49:14 +01:00
Jermolene
e548dd35af Restored drag and drop functionality within TEXTAREAs and INPUTs
As mentioned by @Skeeve in #592
2014-05-07 14:32:14 +01:00
Jermolene
8b20143b1b Pass content-type to codemirror mode option for syntax highlight
Fixes #605
2014-05-07 14:09:46 +01:00
Jeremy Ruston
711b76307c Merge pull request #604 from natecain/module_exports
Module exports
2014-05-07 14:05:45 +01:00
Jermolene
b858e9dc69 Fix incorrect filter in shadow $:/DefaultTiddlers
Fixes #606
2014-05-07 13:43:12 +01:00
Jermolene
a9411262f7 Improve TiddlyWiki as a library
1. Make it possible to disable specific boot tasks
2. Extend the startup mechanism to allow startup tasks to be disabled

Again, see Jermolene/TiddlyWiki5NodeWebkit to see how these features
fit together.
2014-05-07 12:51:16 +01:00
Jermolene
e676156b24 Fixes for running TiddlyWiki on node-webkit
See Jermolene/TiddlyWiki5NodeWebkit
2014-05-07 09:59:21 +01:00
natecain
c592e658e7 Fix up codemirror instructions to match new paths in config example 2014-05-06 23:57:10 +02:00
natecain
6b03789e06 Prioritize "module.exports" over "exports" in require sandbox
(Node-ism, inherited (temporarily?) to support codemirror upgrade)
2014-05-06 23:31:57 +02:00
natecain
51f54b06f9 Upgrade codemirror to current master 2014-05-06 23:30:40 +02:00
Jeremy Ruston
285ab41ccf Merge pull request #602 from BramChen/master
Add chinese translation of banner for binary tiddlers in edit mode
2014-05-06 20:15:43 +01:00
Jermolene
854b739a35 Implement explicit external links 2014-05-06 20:05:51 +01:00
Jermolene
abe0ce28b9 Fix typos in docs for image parser 2014-05-06 19:00:34 +01:00
Jermolene
76e8640c31 Fix problem with parsing lists contain non-breaking spaces
Some of the time we need to treat non-breaking spaces as though they
are not spaces (regexps treat them as spaces by default).
2014-05-06 18:10:27 +01:00
Jermolene
cc3d44aec1 Fix problem with list fields containing [[]]
Fixes #603 - thanks @xcazin!

It no longer crashes but unfortunately if you round trip a tiddler out
of edit mode and back you’ll lose any empty double square brackets.
2014-05-06 17:32:12 +01:00
Bram Chen
7b6cff0cca Fix incorrect charset for the previous commit 2014-05-06 17:36:59 +08:00
Jermolene
d1c85f53c0 Update release note 2014-05-06 10:33:08 +01:00
Bram Chen
e2b0da0b58 Add chinese translation of banner for binary tiddlers in edit mode 2014-05-06 17:23:27 +08:00
Jermolene
7c8c5cf745 Fix problem with parsing main UI boot tiddlers
We were parsing the boot tiddlers, making them into a widget and then
refreshing the widget tree. The problem is that subsequent chances to
the boot tiddlers themselves wouldn’t be picked up as part of the
refresh.

Now we indirectly parse those UI boot tiddlers through a transclusion,
which does get refreshed in the desired way.
2014-05-06 10:14:22 +01:00
Jermolene
38c60bd7d4 Fix tag colour 2014-05-05 23:19:49 +01:00
Jermolene
afb92c40fe Tweak ribbon colour for 5.0.11 2014-05-05 23:19:41 +01:00
Jermolene
6b45296ca9 Roadmap and release note updates 2014-05-05 23:19:30 +01:00
Jermolene
b84c663215 Add proper rendering of document title 2014-05-05 23:00:09 +01:00
Jermolene
4e101e240c Suppress history when changing the permalink URL 2014-05-05 21:51:54 +01:00
Jermolene
56251dc1f8 Fixes #598
Ensure we don’t generate permalinks with a target that is not in the
current story
2014-05-05 21:23:29 +01:00
Jermolene
f368175cb0 Remove debugging code 2014-05-05 20:58:47 +01:00
Jeremy Ruston
3e49dd65a0 Merge pull request #594 from xcazin/fr-FR
fr-FR translations for warnings about shadow tiddlers and binary content
2014-05-05 20:57:28 +01:00
Jermolene
f5ada72dac Ensure tag colours are specified in hex 2014-05-05 19:25:49 +01:00
Jermolene
986a20b22b Fixes for permalinks not working on Firefox
Sigh. It’s frustrating that the few browser differences I’m running
into in 2014 are mostly horribly familiar from 2005
2014-05-05 19:21:57 +01:00
Jermolene
ffb6c8ab81 Add hex colours to tag manager
Fixes #597
2014-05-05 18:42:25 +01:00
Jermolene
e58e68fa7c Add Matabele's gTD site 2014-05-05 17:31:52 +01:00
Jermolene
95def8b857 Add startup sequence diagram 2014-05-05 17:06:34 +01:00
Jermolene
b24ec8009d Missing dependency 2014-05-05 17:06:24 +01:00
Jermolene
9965c64b6f More refactoring of startup.js 2014-05-05 15:25:51 +01:00
Jermolene
2a50277219 Fix problem with syncer not being initialised on server 2014-05-05 14:44:32 +01:00
Jermolene
3cce12e13f More refactoring of startup.js 2014-05-05 14:41:46 +01:00
Jermolene
887e9d978b Fix problem with saving if URL contains # 2014-05-05 13:30:31 +01:00
Jermolene
a0022a1cd6 Refactoring more of startup.js into modules 2014-05-05 10:17:50 +01:00
Jermolene
519e1b4a44 Pull more of startup.js out into separate modules 2014-05-03 21:23:51 +01:00
Jermolene
b9dec37fb7 Split main rendering into it's own startup module 2014-05-03 19:50:05 +01:00
Jermolene
09156af475 Add support for "before" field on startup modules 2014-05-03 19:49:50 +01:00
Jermolene
5b5621a600 Fix googleanalytics plugin to be platform-specific 2014-05-03 18:07:20 +01:00
Jermolene
78ba57d55d Remove support for browser-startup modules
Instead support startup modules that stipulate which platform they
require.

Also include docs updates and fixes to fullscreen plugin
2014-05-03 17:49:20 +01:00
Jermolene
749582ede0 Split module loading into a separate startup task
Still a work in progress.
2014-05-03 17:10:55 +01:00
Jermolene
1c82348edb Docs typo 2014-05-03 16:56:29 +01:00
Jermolene
b96aade28a WIP: Add support for dependencies between startup modules
See StartupMechanism for details.
2014-05-03 16:32:18 +01:00
Jermolene
2f32621024 Docs updates 2014-05-03 16:27:22 +01:00
Jermolene
6ccf02ed96 Add support for onhashchange
Now we respond dynamically to changes in the location hash in the URL
bar. It means that you can do links in HTML as `<a
href=“#HelloThere”>go</a>` and in Markdown as `[example
link](#HelloThere).`

We still need to make startup.js more modular
2014-05-03 12:20:28 +01:00
Jermolene
b2c1331c11 Fix oversight in isDraftModified
If the original tiddler doesn’t exist then we should count the draft as
always having been modified
2014-05-03 12:12:07 +01:00
Xavier Cazin
f81df69395 Change references to editions/clientserver into editions/server 2014-05-03 13:10:36 +02:00
Jermolene
a5e9ef9b5f Adopt new URL scheme for permalinks
Instead of using `%00` as a separator we do the more conventional
`#!<target-title>:<story filter>`.
2014-05-03 11:32:55 +01:00
Xavier Cazin
7783378603 fr-FR translations for shadow tiddlers and binary content warnings 2014-05-02 23:00:13 +02:00
Jermolene
327b53a641 Start adding support for permalinks
At this point we respect any permalink at startup, but we don’t yet
dynamically update the permalink, nor do we respond to ongoing
permalink changes.

The permalink separator being `%00` seems like it might be a bit
controversial. It buys us not having to wrap tiddler titles in double
square brackets if they contain spaces.

Another thing is that this scheme doesn’t support tiddler filters; the
plan is to support them like this:

http://tiddlywiki.com/#!Target%00%00[tag[task]sort[created]]
2014-05-02 19:21:32 +01:00
Jermolene
cb914ae853 Remove dead code typo 2014-05-02 18:07:47 +01:00
Jermolene
a4294b55f0 Add banner for binary tiddlers in edit mode
Makes it easier to add tags to a binary tiddler (eg a PDF).
2014-05-02 09:43:39 +01:00
Jermolene
bced7124e4 Accept single quotes for attributes in TW files 2014-05-01 17:58:49 +01:00
Jermolene
f5848c395a Fix problem with editing tiddler titles
The check whether a draft has been modified was ignoring changes to the
title.

Fixes #593
2014-05-01 17:39:37 +01:00
Jermolene
f6bd3b8c37 Optimise the all filter operator
Seems like quite a decent optimisation.
2014-04-30 22:50:47 +01:00
Jermolene
21b2d6fdc7 Allow filter operators to return an iterator
Previously filter operators were only permitted to return an array of
tiddler titles
2014-04-30 22:50:17 +01:00
Jermolene
bd3e955821 Add compound iterators to boot wiki object 2014-04-30 22:49:28 +01:00
Jermolene
fcb26419a6 Clear the tiddler event queue on startup
To avoid an unnecessary refresh cycle
2014-04-30 22:49:02 +01:00
Jermolene
a6f7da6c1c Suppress refresh cycle if no tiddlers have changed 2014-04-30 22:48:36 +01:00
Jeremy Ruston
f82f8ae7c6 Merge pull request #589 from BramChen/master
Add chinese messages for editing/overridden a shadow tiddler
2014-04-29 09:04:44 +01:00
Jermolene
edb8c65d54 Update release note 2014-04-29 09:03:47 +01:00
Jermolene
031c0f4146 Update HelloThere 2014-04-29 09:03:39 +01:00
Bram Chen
e8316cf0ac Add chinese messages for editing/overridden a shadow tiddler 2014-04-29 15:32:19 +08:00
Jermolene
0ac4c2b554 Allow digits in field names 2014-04-28 15:54:32 +01:00
Jermolene
84cd296c58 Minor tweaks to shadow warning infrastructure
1. Moved some methods out of boot.js because they are not needed until
after bootup
2. Added alternate message for editing an overridden shadow tiddler
3. Minor style tweaks
2014-04-28 15:16:31 +01:00
Jeremy Ruston
a90339d1e5 Merge pull request #586 from sukima/feature/issue-570-cancle-unchanged-drafts
Fix issue #570 Make it harder to accidentally modify a shadow tiddler
2014-04-28 13:22:44 +01:00
Jermolene
d49495ab73 Add docs for "field" filter operator
Fixes #588
2014-04-28 12:54:34 +01:00
Jeremy Ruston
5fa6d001f8 Merge pull request #587 from BramChen/master
Update chinese editions
2014-04-28 09:36:32 +01:00
Jermolene
f17dafefcb Docs updates 2014-04-28 09:33:47 +01:00
Bram Chen
88314d968a Add build targets to chinese editions 2014-04-28 16:11:57 +08:00
Bram Chen
28bab707b9 Update chinese translations for Help tiddlers 2014-04-28 16:02:58 +08:00
Devin Weaver
075cf544e4 Use new get filter from commit 570cad1c 2014-04-27 17:15:42 -04:00
Devin Weaver
a505b6ffc0 Move isModified from Tiddler to Wiki
Replace this with a $tw.wiki.isModifiedTiddler(title) as part of the
wiki object. This allows it to be used outside of the current Wiki which
can change.
2014-04-27 17:15:42 -04:00
Devin Weaver
23a71b433e Rename isEqual to isArrayEqual 2014-04-27 17:15:42 -04:00
Devin Weaver
3bbe53a58e Move shadowWarning to it's own template segment 2014-04-27 17:15:42 -04:00
Devin Weaver
8556e0ea49 Fix coding style 2014-04-27 17:15:42 -04:00
Devin Weaver
3be21853e1 Add warning box while editing a shadow tiddler
This addresses the third line item of issue #570

TODO: The filter is not working.
TODO: The message is too genaric and needs help.
2014-04-27 17:15:42 -04:00
Devin Weaver
d0636f2124 Add a confirmation to edit a shadow tiddler
Should only display the confirmation if the shadow tiddler has not been
overridden in the first place. It checks this by looking for the
existence of a modified field for which the default system based shadow
do not have until a user changes them.

This addresses the second line item on issue #570

We will need new translations for the added string
`ConfirmEditShadowTiddler`
2014-04-27 17:15:42 -04:00
Devin Weaver
5226c7a2fa Prevent saving un-modified tiddlers
When saving a tiddler we check to see if the tiddler has changed
(isModified) if it hasn't then bounce the event to tw-cancel-tiddler
instead.

Addresses first line item in issue #570
2014-04-27 17:15:42 -04:00
Devin Weaver
3a78465d2d Add isModified to Tiddler object
Adds a check to see if this tiddler differers from the tiddler
referenced in the draft.of field. It iterates of the fields property
skiping those feilds that offer a false positives. Uses the isEqual util
for the tags array.
2014-04-27 17:15:42 -04:00
Devin Weaver
23640d7af4 Add isDraft to Tiddler object
Check to see if this tiddler is a draft (has a draft.of field)
2014-04-27 17:15:42 -04:00
Devin Weaver
540681b2bc Add $tw.util.isEqual
This checks to see if an array is equal. Should handle case where an
array is considered null or undefined. It short circuits when the
lengths are different and will only loop when needed.
2014-04-27 17:15:42 -04:00
Devin Weaver
8611867930 Remove dead code 💀 2014-04-27 17:15:41 -04:00
Jermolene
77152ac577 Update release note 2014-04-27 21:58:59 +01:00
Jermolene
f5bd99fa73 Fix tests for 385c7e207c 2014-04-27 21:58:41 +01:00
Jermolene
385c7e207c Refactor wiki.filterTiddlers()
Now we pass a widget instead of the current tiddler title. We can use
widget.getVariable(“currentTiddler”) to get the current tiddler.
2014-04-27 20:03:33 +01:00
Jermolene
61c204366f Replace hamburger icon with double chevron
Fixes #580

Seems much better, especially since the chevron gives us two clear
visual states (left vs. right). The hamburger doesn’t really have a
commonly accepted way of indicating whether the menu is currently open
or not.
2014-04-27 19:28:30 +01:00
Jermolene
570cad1c7f Add 'get' filter operator
Prompted by @sukima’s work on #586
2014-04-27 18:45:01 +01:00
Jeremy Ruston
1d0dc60a2d Merge pull request #574 from pekopeko1/japanese
Updated Japanese Translation
2014-04-27 08:47:59 +01:00
Jeremy Ruston
fac0affa7b Merge pull request #584 from xcazin/fr-FR
fr-FR translations for new Help tiddlers + changes to previous ones.
2014-04-27 08:46:59 +01:00
Jeremy Ruston
f57241abbd Merge pull request #585 from BramChen/master
Update chinese translations for Help tiddlers
2014-04-27 08:46:41 +01:00
Jermolene
e9557b578e Improve output directory handling
This change is likely to break most existing scripts that call
TiddlyWiki.

TL;DR - output paths are now relative to the editions/output folder,
rather than to the current folder

See [[Notes for upgrading to 5.0.11-beta]] for details.
2014-04-27 08:28:21 +01:00
Jermolene
649f68288a Add build targets to the core editions 2014-04-26 17:11:56 +01:00
pekopeko1
37c50bae61 merged with latest master 2014-04-27 00:14:41 +09:00
pekopeko1
9ab31e37ea fix plugin.info author 2014-04-26 23:11:31 +09:00
pekopeko1
30707e2f19 revert unnecessary .gitignore change 2014-04-26 23:09:42 +09:00
Bram Chen
1fb76ae56d Fix typo 2014-04-26 20:10:02 +08:00
Bram Chen
4008191459 Update chinese translations for Help tiddlers 2014-04-26 19:52:45 +08:00
Xavier Cazin
463bd0517c fr-FR translation for new Help tiddlers 2014-04-26 11:56:40 +02:00
Xavier Cazin
fb3a31ae43 Typo: Set => Clear 2014-04-26 11:12:59 +02:00
Jermolene
f7e50e0950 Add --build command
First pass at the build system described in #356.

To test it, move to a new, empty directory and try `tiddlywiki
editions/tw5.com --verbose --build`
2014-04-25 22:41:59 +01:00
Jermolene
552657fc58 Fix text parser to use codeblocks
This means that JavaScript and JSON tiddlers will be properly
highlighted if the highlight plugin is loaded.
2014-04-24 19:41:07 +01:00
Jermolene
d727046948 Revise number of tiddlers in recent changes list
Going back to 100; 250 was a typo.
2014-04-24 12:22:31 +01:00
Jermolene
f6ca7d92e5 Fix docs typo
Fixes #575
2014-04-24 11:59:51 +01:00
Jermolene
148e77b0e4 Clean up obsolete macro definition
Fixes #576
2014-04-24 11:58:42 +01:00
Jermolene
cc60ad1428 Fixed topbar hover for Firefox
Pesky Firefox browser crankiness.

Fixes #579
2014-04-24 11:33:14 +01:00
Jermolene
fecf3a556f Update JS macro docs 2014-04-24 11:08:23 +01:00
Jeremy Ruston
39ef0ad88f Merge pull request #581 from mwfogleman/tid-mode
Refer Emacs docs to tid-mode, not tid-time.
2014-04-24 09:01:27 +01:00
Michael Fogleman
f75826224b Refer Emacs docs to tid-mode, not tid-time. 2014-04-24 11:39:37 +05:30
Jeremy Ruston
52f28a1cc3 Merge pull request #578 from sukima/feature/sign-cla-sukima
Add @sukima to cla-individual.md
2014-04-22 15:49:35 +01:00
Jermolene
61c3f8a5ba Remove wikitext tiddlers from "types" sidebar tab 2014-04-22 11:44:27 +01:00
Devin Weaver
13da54b9bd Add @sukima to cla-individual.md 2014-04-21 18:26:04 -04:00
pekopeko1
680414d1c5 edited 'shadow' translation 2014-04-20 23:33:27 +09:00
pekopeko1
2c7d5c5964 merged @ogoshima's translation 2014-04-20 23:24:35 +09:00
Jermolene
3d69c929d9 Add more warnings about backups 2014-04-19 14:42:22 +01:00
Jeremy Ruston
8cbcfee346 Merge pull request #573 from pmario/fix-concepts-tiddlerfields-lingo
Fix "description" column in TiddlerFields
2014-04-19 14:23:06 +01:00
Jermolene
43173c801f Adjust version number for 5.0.11 2014-04-19 14:22:25 +01:00
Mario Pietsch
523faf71fb change modified date 2014-04-19 15:16:12 +02:00
Mario Pietsch
ad2bbb2c93 tiddler: TiddlerFields - fix the description column. 2014-04-19 15:11:20 +02:00
Jermolene
8756d25d78 Version number update for 5.0.10-beta 2014-04-19 14:07:48 +01:00
Jermolene
8a27c2759b Update 5.0.10 release date 2014-04-19 14:06:29 +01:00
Jermolene
beddcd7138 New ribbon colour for 5.0.10 2014-04-19 13:15:24 +01:00
Jermolene
2db90378a2 Release note updates for 5.0.10 2014-04-19 11:34:23 +01:00
Jermolene
7684891285 Move topbar out of the way of scrollbars
In the process getting rid of some extraneous `<p>` tags.

Fixes #566
2014-04-19 11:32:56 +01:00
Jermolene
821f1f1428 Fix hamburger and seamless behaviour
No longer remove the tiddler borders when hiding the sidebar; users can
select Seamless theme to get the same effect.

Fixes #566
2014-04-19 11:24:41 +01:00
Jermolene
4538f081ee Release note updates for 5.0.10 2014-04-19 11:22:59 +01:00
Jermolene
b4122be50c Update release note for 5.0.10 2014-04-19 11:18:08 +01:00
Jermolene
cd76514105 Update roadmap 2014-04-19 09:36:14 +01:00
Jermolene
ba576d9f1b Add support for safe mode 2014-04-19 09:36:08 +01:00
Jermolene
15d0c27e2a Add [is[tag]] filter operator 2014-04-18 17:57:55 +01:00
Jermolene
869cec1ccc Add docs for date format strings 2014-04-18 17:37:13 +01:00
Jermolene
d6054f1039 Fix problem with offline copy of server edition
We were accidentally including all the shadow tiddlers as well as
ordinary ones.
2014-04-18 15:23:00 +01:00
Jermolene
9fbe72a877 Rearrange system tag configuration
By rearranging the `[all[]]` operator we are able to ensure that shadow
tiddlers get processed before ordinary tiddlers. This makes it easier
to create custom stylesheets that override the core.
2014-04-18 09:28:14 +01:00
Jermolene
89165fc51d Fix problem with sorting date fields
Introduced a couple of commits ago when the localeCompare() stuff was
added.
2014-04-17 22:52:57 +01:00
Jermolene
4758874d13 Add path conversions from TiddlyWiki Classic
TiddlyWiki Classic converts local file URIs to various local native
formats. The same conversions are now performed by the TiddlyFox
adaptor for TW5.
2014-04-17 22:30:14 +01:00
Jermolene
0153fd2a30 Correct typos in 5.0.9 release note 2014-04-17 20:26:35 +01:00
Jermolene
bb42c0ab36 Use localCompare for sorting strings
So that accented characters get sorted correctly. Or at least as
correctly as browsers allow.
2014-04-17 20:15:52 +01:00
Jermolene
95d291daac Update print stylesheet to hide topbar 2014-04-17 19:50:12 +01:00
Jermolene
45b0966013 Support the image widget in markdown 2014-04-17 16:50:54 +01:00
Jermolene
de07da3797 Revise warning about backing up before upgrading 2014-04-17 16:26:57 +01:00
Jeremy Ruston
aebc1ea943 Merge pull request #562 from pmario/upgrade-backup-info
add a backup info for the Upgrade tiddler.
2014-04-17 16:24:57 +01:00
Jermolene
73cfd10218 Fix regression with untagged filter operator
Restored previous behaviour of considering a missing tiddler to be
untagged.
2014-04-17 16:10:50 +01:00
Jermolene
d336ffea02 Fix incorrect background colour for sidebar tag pills
Fixes #568.
2014-04-17 15:11:59 +01:00
Jermolene
6da28e7365 Docs update 2014-04-17 14:44:14 +01:00
Jermolene
d08a2d109f Fix html parser tests 2014-04-17 14:43:24 +01:00
Jermolene
f57e047877 Fix issues with tiddlers with null fields
Fixing #567
2014-04-17 14:43:12 +01:00
Jermolene
df5fe10a40 Start release note for 5.0.10 2014-04-17 12:52:52 +01:00
Jermolene
433ac8e96e Typo fix 2014-04-17 12:52:38 +01:00
Jermolene
ad4b03506a Added wikitext image support
We’ve added a parser to recognise the `[img[URL or tiddler title]]`
format, and an associated image widget.
2014-04-17 12:52:32 +01:00
Jermolene
ace57dd205 Refactor utilities out of HTML parser
Some of the functions are useful general purpose parser helpers.
2014-04-17 12:00:32 +01:00
Jermolene
bd4a031df8 Fix problem with version checking logic
Previously, importing a plugin with a semantically identical version
number was not rejected. This meant that attempts to import
5.0.9-prerelease wikis into 5.0.9-beta led to a corrupted wiki, with a
beta core and prerelease plugins.
2014-04-17 11:59:42 +01:00
Jermolene
6db94052c7 Prepare for 5.0.10 release 2014-04-17 11:58:16 +01:00
Mario Pietsch
dd8797223a add a backup info for the Upgrade tiddler. 2014-04-16 01:09:26 +02:00
Jermolene
e54b0d7129 Docs fixes 2014-04-15 21:50:36 +01:00
Jermolene
07ab8c75b8 Docs fixes 2014-04-15 21:48:19 +01:00
OGOSHI Masayuki
5bcc666f34 Update some translations. 2014-04-16 02:40:49 +09:00
OGOSHI Masayuki
6bef1d6b30 Update command line helps Japanese Translation. 2014-04-15 23:44:05 +09:00
OGOSHI Masayuki
09cf788063 Merge branch 'master' into ja-JP 2014-04-14 17:03:16 +09:00
OGOSHI Masayuki
4d0b08d464 some translations corrected. 2014-04-13 15:52:41 +09:00
OGOSHI Masayuki
5447420832 1st time ja-JP translation commit. 2014-04-13 15:35:36 +09:00
491 changed files with 17981 additions and 8709 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.DS_Store
tmp/
output/

View File

@@ -2,22 +2,13 @@
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 ^
--output editions\tw2 ^
--rendertiddler TiddlyWiki2ReadMe readme.md text/html ^
|| exit 1
rem cook the TiddlyWiki 2.x.x index file
@@ -25,8 +16,9 @@ rem cook the TiddlyWiki 2.x.x index file
node .\tiddlywiki.js ^
editions\tw2 ^
--verbose ^
--output tmp\tw2 ^
--load editions\tw2\source\tiddlywiki.com\index.html.recipe ^
--rendertiddler $:/core/templates/tiddlywiki2.template.html .\tmp\tw2\index.html text/plain ^
--rendertiddler $:/core/templates/tiddlywiki2.template.html index.html text/plain ^
|| exit 1
fc tmp\tw2\index.html editions\tw2\target\prebuilt.html

10
2bld.sh
View File

@@ -2,16 +2,13 @@
# build TiddlyWiki 2.x
# create a temporary directory if it doesn't already exist
mkdir -p tmp
mkdir -p tmp/tw2
# 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 \
--output editions/tw2 \
--rendertiddler TiddlyWiki2ReadMe readme.md text/html \
|| exit 1
# cook the TiddlyWiki 2.x.x index file
@@ -19,8 +16,9 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
editions/tw2 \
--verbose \
--output tmp/tw2 \
--load editions/tw2/source/tiddlywiki.com/index.html.recipe \
--rendertiddler $:/core/templates/tiddlywiki2.template.html ./tmp/tw2/index.html text/plain \
--rendertiddler $:/core/templates/tiddlywiki2.template.html index.html text/plain \
|| exit 1
diff -q tmp/tw2/index.html editions/tw2/target/prebuilt.html

View File

@@ -25,28 +25,32 @@ echo "tiddlywiki.com" > $TW5_BUILD_OUTPUT/CNAME
node ./tiddlywiki.js \
./editions/de-AT-DE \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/de-AT-DE.html text/plain \
--savetiddler $:/favicon.ico $TW5_BUILD_OUTPUT/favicon.ico \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all de-AT-DE.html text/plain \
--savetiddler $:/favicon.ico favicon.ico \
|| exit 1
node ./tiddlywiki.js \
./editions/zh-Hant \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/zh-Hant.html text/plain \
--savetiddler $:/favicon.ico $TW5_BUILD_OUTPUT/favicon.ico \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all zh-Hant.html text/plain \
--savetiddler $:/favicon.ico favicon.ico \
|| exit 1
node ./tiddlywiki.js \
./editions/zh-Hans \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/zh-Hans.html text/plain \
--savetiddler $:/favicon.ico $TW5_BUILD_OUTPUT/favicon.ico \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all zh-Hans.html text/plain \
--savetiddler $:/favicon.ico favicon.ico \
|| exit 1
node ./tiddlywiki.js \
./editions/fr-FR \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/fr-FR.html text/plain \
--savetiddler $:/favicon.ico $TW5_BUILD_OUTPUT/favicon.ico \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all fr-FR.html text/plain \
--savetiddler $:/favicon.ico favicon.ico \
|| exit 1

35
bld.cmd
View File

@@ -34,18 +34,10 @@ 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 ^
--output . ^
--build readmes ^
--output %TW5_BUILD_OUTPUT% ^
--build favicon empty static index ^
|| exit 1
rem encrypted.html: a version of the main file encrypted with the password "password"
@@ -53,8 +45,8 @@ rem encrypted.html: a version of the main file encrypted with the password "pass
node .\tiddlywiki.js ^
.\editions\tw5.com ^
--verbose ^
--password password ^
--rendertiddler $:/core/save/all %TW5_BUILD_OUTPUT%\encrypted.html text/plain ^
--output %TW5_BUILD_OUTPUT% ^
--build encrypted ^
|| exit 1
rem tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
@@ -62,7 +54,8 @@ 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 ^
--output %TW5_BUILD_OUTPUT% ^
--rendertiddler $:/core/save/all tahoelafs.html text/plain ^
|| exit 1
rem d3demo.html: wiki to demo d3 plugin
@@ -70,7 +63,8 @@ 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 ^
--output %TW5_BUILD_OUTPUT% ^
--rendertiddler $:/core/save/all d3demo.html text/plain ^
|| exit 1
rem codemirrordemo.html: wiki to demo codemirror plugin
@@ -78,7 +72,8 @@ 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 ^
--output %TW5_BUILD_OUTPUT% ^
--rendertiddler $:/core/save/all codemirrordemo.html text/plain ^
|| exit 1
rem markdowndemo.html: wiki to demo markdown plugin
@@ -86,7 +81,8 @@ 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 ^
--output %TW5_BUILD_OUTPUT% ^
--rendertiddler $:/core/save/all markdowndemo.html text/plain ^
|| exit 1
@@ -95,7 +91,8 @@ 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 ^
--output %TW5_BUILD_OUTPUT% ^
--rendertiddler $:/core/save/all highlightdemo.html text/plain ^
|| exit 1
rem Make the CNAME file that GitHub Pages requires

35
bld.sh
View File

@@ -35,18 +35,10 @@ rm $TW5_BUILD_OUTPUT/static/*
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 \
--output . \
--build readmes \
--output $TW5_BUILD_OUTPUT \
--build favicon empty static index \
|| exit 1
# encrypted.html: a version of the main file encrypted with the password "password"
@@ -54,8 +46,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/tw5.com \
--verbose \
--password password \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/encrypted.html text/plain \
--output $TW5_BUILD_OUTPUT \
--build encrypted \
|| exit 1
# tahoelafs.html: empty wiki with plugin for Tahoe-LAFS
@@ -63,7 +55,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/tahoelafs \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/tahoelafs.html text/plain \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all tahoelafs.html text/plain \
|| exit 1
# d3demo.html: wiki to demo d3 plugin
@@ -71,7 +64,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/d3demo \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/d3demo.html text/plain \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all d3demo.html text/plain \
|| exit 1
# codemirrordemo.html: wiki to demo codemirror plugin
@@ -79,7 +73,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/codemirrordemo \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/codemirrordemo.html text/plain \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all codemirrordemo.html text/plain \
|| exit 1
# markdowndemo.html: wiki to demo markdown plugin
@@ -87,7 +82,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/markdowndemo \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/markdowndemo.html text/plain \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all markdowndemo.html text/plain \
|| exit 1
# highlightdemo.html: wiki to demo highlight plugin
@@ -95,7 +91,8 @@ node ./tiddlywiki.js \
node ./tiddlywiki.js \
./editions/highlightdemo \
--verbose \
--rendertiddler $:/core/save/all $TW5_BUILD_OUTPUT/highlightdemo.html text/plain \
--output $TW5_BUILD_OUTPUT \
--rendertiddler $:/core/save/all 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

View File

@@ -33,7 +33,6 @@ if(!$tw) {
}
$tw.utils = $tw.utils || Object.create(null);
$tw.boot = $tw.boot || Object.create(null);
/////////////////////////// Standard node.js libraries
@@ -46,6 +45,11 @@ if($tw.node) {
/////////////////////////// Utility functions
$tw.boot.log = function(str) {
$tw.boot.logMessages = $tw.boot.logMessages || [];
$tw.boot.logMessages.push(str);
}
/*
Check if an object has a property
*/
@@ -131,7 +135,7 @@ $tw.utils.error = function(err) {
promptMsg = "Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser";
// Log the error to the console
console.error(err);
if($tw.browser) {
if($tw.browser && !$tw.node) {
// Display an error message to the user
var dm = $tw.utils.domMaker,
heading = dm("h1",{text: errHeading}),
@@ -146,7 +150,7 @@ $tw.utils.error = function(err) {
return false;
},true);
return null;
} else {
} else if(!$tw.browser) {
// Exit if we're under node.js
process.exit(1);
}
@@ -155,7 +159,7 @@ $tw.utils.error = function(err) {
/*
Use our custom error handler if we're in the browser
*/
if($tw.browser) {
if($tw.boot.tasks.trapErrors) {
window.onerror = function(errorMsg,url,lineNumber) {
$tw.utils.error(errorMsg);
return false;
@@ -183,11 +187,11 @@ $tw.utils.deepDefaults = function(object /*, sourceObjectList */) {
$tw.utils.each(Array.prototype.slice.call(arguments,1),function(source) {
if(source) {
for (var p in source) {
if(object[p] == null) {
if(object[p] === null || object[p] === undefined) {
object[p] = source[p];
}
if(typeof object[p] === "object" && typeof source[p] === "object") {
$tw.utils.deepDefaults(object[p],source[p]);
$tw.utils.deepDefaults(object[p],source[p]);
}
}
}
@@ -202,6 +206,14 @@ $tw.utils.htmlDecode = function(s) {
return s.toString().replace(/&lt;/mg,"<").replace(/&nbsp;/mg,"\xA0").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};
/*
Get the browser location.hash. We don't use location.hash because of the way that Firefox auto-urldecodes it (see http://stackoverflow.com/questions/1703552/encoding-of-window-location-hash)
*/
$tw.utils.getLocationHash = function() {
var parts = window.location.href.split('#');
return "#" + (parts.length > 1 ? parts[1] : "");
};
/*
Pad a string to a given length with "0"s. Length defaults to 2
*/
@@ -218,8 +230,8 @@ $tw.utils.pad = function(value,length) {
$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.getUTCDate()) +
$tw.utils.pad(value.getUTCHours()) +
$tw.utils.pad(value.getUTCMinutes()) +
$tw.utils.pad(value.getUTCSeconds()) +
$tw.utils.pad(value.getUTCMilliseconds(),3);
@@ -258,14 +270,14 @@ $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)(?:\[\[(.*?)\]\])(?=\s|$)|(\S+)/mg,
var memberRegExp = /(?:^|[^\S\xA0])(?:\[\[(.*?)\]\])(?=[^\S\xA0]|$)|([\S\xA0]+)/mg,
results = [],
match;
do {
match = memberRegExp.exec(value);
if(match) {
var item = match[1] || match[2];
if(results.indexOf(item) === -1) {
if(item !== undefined && results.indexOf(item) === -1) {
results.push(item);
}
}
@@ -301,7 +313,6 @@ name `.` refers to the current directory
*/
$tw.utils.resolvePath = function(sourcepath,rootpath) {
// If the source path starts with ./ or ../ then it is relative to the root
if(sourcepath.substr(0,2) === "./" || sourcepath.substr(0,3) === "../" ) {
var src = sourcepath.split("/"),
root = rootpath.split("/");
@@ -352,7 +363,7 @@ $tw.utils.parseVersion = function(version) {
};
/*
Returns true if the version string A is greater than the version string B
Returns true if the version string A is greater than the version string B. Returns true if the versions are the same
*/
$tw.utils.checkVersions = function(versionStringA,versionStringB) {
var defaultVersion = {
@@ -369,7 +380,8 @@ $tw.utils.checkVersions = function(versionStringA,versionStringB) {
];
return (diff[0] > 0) ||
(diff[0] === 0 && diff[1] > 0) ||
(diff[0] === 0 && diff[1] === 0 && diff[2] > 0);
(diff[0] === 0 && diff[1] === 0 && diff[2] > 0) ||
(diff[0] === 0 && diff[1] === 0 && diff[2] === 0);
};
/*
@@ -380,8 +392,8 @@ options: {flags: flags,deserializerType: deserializerType}
*/
$tw.utils.registerFileType = function(type,encoding,extension,options) {
options = options || {};
$tw.config.fileExtensionInfo[extension] = {type: type};
$tw.config.contentTypeInfo[type] = {encoding: encoding, extension: extension, flags: options.flags || [], deserializerType: options.deserializerType || type};
$tw.config.fileExtensionInfo[extension] = {type: type};
$tw.config.contentTypeInfo[type] = {encoding: encoding, extension: extension, flags: options.flags || [], deserializerType: options.deserializerType || type};
};
/*
@@ -413,7 +425,7 @@ $tw.utils.evalGlobal = function(code,context,filename) {
if($tw.browser) {
fn = window["eval"](code + "\n\n//# sourceURL=" + filename);
} else {
fn = vm.runInThisContext(code,filename);
fn = vm.runInThisContext(code,filename);
}
// Call the function and return the exports
return fn.apply(null,contextValues);
@@ -553,7 +565,7 @@ Crypto helper object for encrypted content. It maintains the password text in a
the password, and to encrypt/decrypt a block of text
*/
$tw.utils.Crypto = function() {
var sjcl = $tw.browser ? window.sjcl : require("./sjcl.js"),
var sjcl = $tw.node ? require("./sjcl.js") : window.sjcl,
currentPassword = null,
callSjcl = function(method,inputText,password) {
password = password || currentPassword;
@@ -564,7 +576,7 @@ $tw.utils.Crypto = function() {
}
} catch(ex) {
console.log("Crypto error:" + ex);
outputText = null;
outputText = null;
}
return outputText;
};
@@ -652,7 +664,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
return window.require(moduleName);
} catch(e) {}
}
throw "Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name;
throw "Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name;
} else {
// If we don't have a module with that name, let node.js try to find it
return require(moduleName);
@@ -668,6 +680,9 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
} else if(typeof moduleInfo.definition === "string") { // String
moduleInfo.exports = _exports;
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
if(sandbox.module.exports) {
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
}
} else { // Object
moduleInfo.exports = moduleInfo.definition;
}
@@ -749,7 +764,7 @@ $tw.Tiddler = function(/* [fields,] fields */) {
var arg = arguments[c],
src = (arg instanceof $tw.Tiddler) ? arg.fields : arg;
for(var t in src) {
if(src[t] === undefined) {
if(src[t] === undefined || src[t] === null) {
if(t in this.fields) {
delete this.fields[t]; // If we get a field that's undefined, delete any previous field value
}
@@ -764,7 +779,7 @@ $tw.Tiddler = function(/* [fields,] fields */) {
}
// Freeze the field to keep it immutable
if(typeof value === "object") {
Object.freeze(value);
Object.freeze(value);
}
this.fields[t] = value;
}
@@ -834,7 +849,7 @@ $tw.Wiki = function(options) {
tiddlers[title] = tiddler;
this.clearCache(title);
this.clearGlobalCache();
this.enqueueTiddlerEvent(title);
this.enqueueTiddlerEvent(title);
}
}
};
@@ -884,6 +899,37 @@ $tw.Wiki = function(options) {
}
};
// Iterate through all tiddlers and then the shadows
this.eachTiddlerPlusShadows = function(callback) {
for(var title in tiddlers) {
callback(tiddlers[title],title);
}
for(var title in shadowTiddlers) {
if(!Object.prototype.hasOwnProperty.call(tiddlers,title)) {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
}
};
// Iterate through all the shadows and then the tiddlers
this.eachShadowPlusTiddlers = function(callback) {
for(var title in shadowTiddlers) {
if(Object.prototype.hasOwnProperty.call(tiddlers,title)) {
callback(tiddlers[title],title);
} else {
var shadowInfo = shadowTiddlers[title];
callback(shadowInfo.tiddler,title);
}
}
for(var title in tiddlers) {
if(!Object.prototype.hasOwnProperty.call(shadowTiddlers,title)) {
callback(tiddlers[title],title);
}
}
};
// Test for the existence of a tiddler
this.tiddlerExists = function(title) {
return !!$tw.utils.hop(tiddlers,title);
@@ -994,15 +1040,15 @@ $tw.Wiki = function(options) {
};
// Dummy methods that will be filled in after boot
$tw.Wiki.prototype.clearCache =
$tw.Wiki.prototype.clearGlobalCache =
$tw.Wiki.prototype.clearCache =
$tw.Wiki.prototype.clearGlobalCache =
$tw.Wiki.prototype.enqueueTiddlerEvent = function() {};
// Add an array of tiddlers
$tw.Wiki.prototype.addTiddlers = function(tiddlers) {
for(var t=0; t<tiddlers.length; t++) {
this.addTiddler(tiddlers[t]);
}
}
};
/*
@@ -1043,6 +1089,37 @@ $tw.Wiki.prototype.defineShadowModules = function() {
});
};
/*
Enable safe mode by deleting any tiddlers that override a shadow tiddler
*/
$tw.Wiki.prototype.processSafeMode = function() {
var self = this,
overrides = [];
// Find the overriding tiddlers
this.each(function(tiddler,title) {
if(self.isShadowTiddler(title)) {
console.log(title);
overrides.push(title);
}
});
// Assemble a report tiddler
var titleReportTiddler = "TiddlyWiki Safe Mode",
report = [];
report.push("TiddlyWiki has been started in [[safe mode|http://tiddlywiki.com/static/SafeMode.html]]. Most customisations have been disabled by renaming the following tiddlers:")
// Delete the overrides
overrides.forEach(function(title) {
var tiddler = self.getTiddler(title),
newTitle = "SAFE: " + title;
self.deleteTiddler(title);
self.addTiddler(new $tw.Tiddler(tiddler, {title: newTitle}));
report.push("* [[" + title + "|" + newTitle + "]]");
});
report.push()
this.addTiddler(new $tw.Tiddler({title: titleReportTiddler, text: report.join("\n\n")}));
// Set $:/DefaultTiddlers to point to our report
this.addTiddler(new $tw.Tiddler({title: "$:/DefaultTiddlers", text: "[[" + titleReportTiddler + "]]"}));
};
/*
Extracts tiddlers from a typed block of text, specifying default field values
*/
@@ -1098,8 +1175,6 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/tid","tiddlerdeserializer",{
}
if(split.length >= 2) {
fields.text = split.slice(1).join("\n\n");
} else {
fields.text = "";
}
return [fields];
}
@@ -1155,7 +1230,7 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/json","tiddlerdeserializer",{
/////////////////////////// Browser definitions
if($tw.browser) {
if($tw.browser && !$tw.node) {
/*
Decrypt any tiddlers stored within the element with the ID "encryptedArea". The function is asynchronous to allow the user to be prompted for a password
@@ -1274,13 +1349,10 @@ $tw.loadTiddlersBrowser = function() {
}
};
// End of if($tw.browser)
}
} else {
/////////////////////////// Server definitions
if(!$tw.browser) {
/*
Get any encrypted tiddlers
*/
@@ -1289,7 +1361,7 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) {
callback();
};
}
} // End of if($tw.browser && !$tw.node)
/////////////////////////// Node definitions
@@ -1353,7 +1425,7 @@ $tw.loadTiddlersFromPath = function(filepath,excludeRegExp) {
} else {
// If not, read all the files in the directory
$tw.utils.each(files,function(file) {
if(!excludeRegExp.test(file)) {
if(!excludeRegExp.test(file) && file !== "plugin.info") {
tiddlers.push.apply(tiddlers,$tw.loadTiddlersFromPath(filepath + path.sep + file,excludeRegExp));
}
});
@@ -1370,53 +1442,102 @@ Load the tiddlers from a plugin folder, and package them up into a proper JSON p
*/
$tw.loadPluginFolder = function(filepath,excludeRegExp) {
excludeRegExp = excludeRegExp || $tw.boot.excludeRegExp;
var stat, files, pluginInfo, pluginTiddlers = [], f, file, titlePrefix, t;
if(fs.existsSync(filepath)) {
stat = fs.statSync(filepath);
if(stat.isDirectory()) {
// Read the plugin information
pluginInfo = JSON.parse(fs.readFileSync(filepath + path.sep + "plugin.info","utf8"));
// Read the plugin files
files = fs.readdirSync(filepath);
for(f=0; f<files.length; f++) {
file = files[f];
if(!excludeRegExp.test(file) && file !== "plugin.info" && file !== "tiddlywiki.files") {
var tiddlerFiles = $tw.loadTiddlersFromPath(filepath + path.sep + file,excludeRegExp);
$tw.utils.each(tiddlerFiles,function(tiddlerFile) {
pluginTiddlers.push.apply(pluginTiddlers,tiddlerFile.tiddlers);
});
}
}
// Save the plugin tiddlers into the plugin info
pluginInfo.tiddlers = pluginInfo.tiddlers || Object.create(null);
for(t=0; t<pluginTiddlers.length; t++) {
if(pluginTiddlers[t].title) {
pluginInfo.tiddlers[pluginTiddlers[t].title] = pluginTiddlers[t];
if(fs.existsSync(filepath) && fs.statSync(filepath).isDirectory()) {
// Read the plugin information
var pluginInfo = JSON.parse(fs.readFileSync(filepath + path.sep + "plugin.info","utf8"));
// Read the plugin files
var pluginFiles = $tw.loadTiddlersFromPath(filepath,excludeRegExp);
// Save the plugin tiddlers into the plugin info
pluginInfo.tiddlers = pluginInfo.tiddlers || Object.create(null);
for(var f=0; f<pluginFiles.length; f++) {
var tiddlers = pluginFiles[f].tiddlers;
for(var t=0; t<tiddlers.length; t++) {
var tiddler= tiddlers[t];
if(tiddler.title) {
pluginInfo.tiddlers[tiddler.title] = tiddler;
}
}
}
}
// Give the plugin the same version number as the core if it doesn't have one
if(pluginInfo && !("version" in pluginInfo)) {
pluginInfo.version = $tw.packageInfo.version;
}
// Save the plugin tiddler
if(pluginInfo) {
var fields = {
title: pluginInfo.title,
type: "application/json",
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",
"dependents": $tw.utils.stringifyList(pluginInfo["dependents"] || [])
// Give the plugin the same version number as the core if it doesn't have one
if(!("version" in pluginInfo)) {
pluginInfo.version = $tw.packageInfo.version;
}
return fields;
// Use "plugin" as the plugin-type if we don't have one
if(!("plugin-type" in pluginInfo)) {
pluginInfo["plugin-type"] = "plugin";
}
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4);
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {
if($tw.utils.isArray(pluginInfo[field])) {
pluginInfo[field] = $tw.utils.stringifyList(pluginInfo[field]);
}
}
return pluginInfo;
} else {
return null;
return null;
}
};
/*
name: Name of the plugin to find
paths: array of file paths to search for it
Returns the path of the plugin folder
*/
$tw.findLibraryItem = function(name,paths) {
var pathIndex = 0;
do {
var pluginPath = path.resolve(paths[pathIndex],"./" + name)
if(fs.existsSync(pluginPath) && fs.statSync(pluginPath).isDirectory()) {
return pluginPath;
}
} while(++pathIndex < paths.length);
return null;
};
/*
name: Name of the plugin to load
paths: array of file paths to search for it
*/
$tw.loadPlugin = function(name,paths) {
var pluginPath = $tw.findLibraryItem(name,paths);
if(pluginPath) {
var pluginFields = $tw.loadPluginFolder(pluginPath);
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
};
/*
libraryPath: Path of library folder for these plugins (relative to core path)
envVar: Environment variable name for these plugins
Returns an array of search paths
*/
$tw.getLibraryItemSearchPaths = function(libraryPath,envVar) {
var pluginPaths = [path.resolve($tw.boot.corePath,libraryPath)],
env = process.env[envVar];
if(env) {
Array.prototype.push.apply(pluginPaths,env.split(":"));
}
return pluginPaths;
};
/*
plugins: Array of names of plugins (eg, "tiddlywiki/filesystemadaptor")
libraryPath: Path of library folder for these plugins (relative to core path)
envVar: Environment variable name for these plugins
*/
$tw.loadPlugins = function(plugins,libraryPath,envVar) {
if(plugins) {
var pluginPaths = $tw.getLibraryItemSearchPaths(libraryPath,envVar);
for(var t=0; t<plugins.length; t++) {
$tw.loadPlugin(plugins[t],pluginPaths);
}
}
};
@@ -1448,36 +1569,10 @@ $tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
}
});
}
// Load any plugins listed in the wiki info file
if(wikiInfo.plugins) {
var pluginBasePath = path.resolve($tw.boot.corePath,$tw.config.pluginsPath);
for(var t=0; t<wikiInfo.plugins.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(pluginBasePath,"./" + wikiInfo.plugins[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
// Load any themes listed in the wiki info file
if(wikiInfo.themes) {
var themesBasePath = path.resolve($tw.boot.corePath,$tw.config.themesPath);
for(var t=0; t<wikiInfo.themes.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(themesBasePath,"./" + wikiInfo.themes[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
// Load any languages listed in the wiki info file
if(wikiInfo.languages) {
var languagesBasePath = path.resolve($tw.boot.corePath,$tw.config.languagesPath);
for(var t=0; t<wikiInfo.languages.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(languagesBasePath,"./" + wikiInfo.languages[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
}
}
}
// Load any plugins, themes and languages listed in the wiki info file
$tw.loadPlugins(wikiInfo.plugins,$tw.config.pluginsPath,$tw.config.pluginsEnvVar);
$tw.loadPlugins(wikiInfo.themes,$tw.config.themesPath,$tw.config.themesEnvVar);
$tw.loadPlugins(wikiInfo.languages,$tw.config.languagesPath,$tw.config.languagesEnvVar);
// Load the wiki files, registering them as writable
var resolvedWikiPath = path.resolve(wikiPath,$tw.config.wikiTiddlersSubDir);
$tw.utils.each($tw.loadTiddlersFromPath(resolvedWikiPath),function(tiddlerFile) {
@@ -1506,7 +1601,7 @@ $tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir);
if(fs.existsSync(wikiPluginsPath)) {
var pluginFolders = fs.readdirSync(wikiPluginsPath);
for(t=0; t<pluginFolders.length; t++) {
for(var t=0; t<pluginFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiPluginsPath,"./" + pluginFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
@@ -1517,7 +1612,7 @@ $tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
var wikiThemesPath = path.resolve(wikiPath,$tw.config.wikiThemesSubDir);
if(fs.existsSync(wikiThemesPath)) {
var themeFolders = fs.readdirSync(wikiThemesPath);
for(t=0; t<themeFolders.length; t++) {
for(var t=0; t<themeFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiThemesPath,"./" + themeFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
@@ -1528,7 +1623,7 @@ $tw.loadWikiTiddlers = function(wikiPath,parentPaths) {
var wikiLanguagesPath = path.resolve(wikiPath,$tw.config.wikiLanguagesSubDir);
if(fs.existsSync(wikiLanguagesPath)) {
var languageFolders = fs.readdirSync(wikiLanguagesPath);
for(t=0; t<languageFolders.length; t++) {
for(var t=0; t<languageFolders.length; t++) {
pluginFields = $tw.loadPluginFolder(path.resolve(wikiLanguagesPath,"./" + languageFolders[t]));
if(pluginFields) {
$tw.wiki.addTiddler(pluginFields);
@@ -1551,17 +1646,25 @@ $tw.loadTiddlersNode = function() {
}
};
// End of if($tw.node)
// End of if($tw.node)
}
/////////////////////////// Main startup function called once tiddlers have been decrypted
/*
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
Startup TiddlyWiki
*/
$tw.boot.startup = function(options) {
options = options || {};
// Get the URL hash and check for safe mode
$tw.locationHash = "#";
if($tw.browser && !$tw.node) {
if(location.hash === "#:safe") {
$tw.safeMode = true;
} else {
$tw.locationHash = $tw.utils.getLocationHash();
}
}
// Initialise some more $tw properties
$tw.utils.deepDefaults($tw,{
modules: { // Information about each module
@@ -1578,12 +1681,17 @@ $tw.boot.startup = function(options) {
wikiThemesSubDir: "./themes",
wikiLanguagesSubDir: "./languages",
wikiTiddlersSubDir: "./tiddlers",
wikiOutputSubDir: "./output",
jsModuleHeaderRegExpString: "^\\/\\*\\\\(?:\\r?\\n)((?:^[^\\r\\n]*(?:\\r?\\n))+?)(^\\\\\\*\\/$(?:\\r?\\n)?)",
fileExtensionInfo: Object.create(null), // Map file extension to {type:}
contentTypeInfo: Object.create(null) // Map type to {encoding:,extension:}
contentTypeInfo: Object.create(null), // Map type to {encoding:,extension:}
pluginsEnvVar: "TIDDLYWIKI_PLUGIN_PATH",
themesEnvVar: "TIDDLYWIKI_THEME_PATH",
languagesEnvVar: "TIDDLYWIKI_LANGUAGE_PATH",
editionsEnvVar: "TIDDLYWIKI_EDITION_PATH"
}
});
if(!options.readBrowserTiddlers) {
if(!$tw.boot.tasks.readBrowserTiddlers) {
// For writable tiddler files, a hashmap of title to {filepath:,type:,hasMetaFile:}
$tw.boot.files = Object.create(null);
// System paths and filenames
@@ -1636,7 +1744,7 @@ $tw.boot.startup = function(options) {
$tw.Wiki.tiddlerDeserializerModules = Object.create(null);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
// Load tiddlers
if(options.readBrowserTiddlers) {
if($tw.boot.tasks.readBrowserTiddlers) {
$tw.loadTiddlersBrowser();
} else {
$tw.loadTiddlersNode();
@@ -1645,6 +1753,10 @@ $tw.boot.startup = function(options) {
$tw.wiki.readPluginInfo();
$tw.wiki.registerPluginTiddlers("plugin");
$tw.wiki.unpackPluginTiddlers();
// Process "safe mode"
if($tw.safeMode) {
$tw.wiki.processSafeMode();
}
// Register typed modules from the tiddlers we've just loaded
$tw.wiki.defineTiddlerModules();
// And any modules within plugins
@@ -1653,12 +1765,114 @@ $tw.boot.startup = function(options) {
if($tw.crypto) {
$tw.crypto.updateCryptoStateTiddler();
}
// Run any startup modules
// Gather up any startup modules
$tw.boot.remainingStartupModules = []; // Array of startup modules
$tw.modules.forEachModuleOfType("startup",function(title,module) {
if(module.startup) {
module.startup();
$tw.boot.remainingStartupModules.push(module);
}
});
// Keep track of the startup tasks that have been executed
$tw.boot.executedStartupModules = Object.create(null);
$tw.boot.disabledStartupModules = $tw.boot.disabledStartupModules || [];
// Repeatedly execute the next eligible task
$tw.boot.executeNextStartupTask();
};
/*
Execute the remaining eligible startup tasks
*/
$tw.boot.executeNextStartupTask = function() {
// Find the next eligible task
var taskIndex = 0, task,
asyncTaskCallback = function() {
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask();
};
while(taskIndex < $tw.boot.remainingStartupModules.length) {
task = $tw.boot.remainingStartupModules[taskIndex];
if($tw.boot.isStartupTaskEligible(task)) {
// Remove this task from the list
$tw.boot.remainingStartupModules.splice(taskIndex,1);
// Assemble log message
var s = ["Startup task:",task.name];
if(task.platforms) {
s.push("platforms:",task.platforms.join(","));
}
if(task.after) {
s.push("after:",task.after.join(","));
}
if(task.before) {
s.push("before:",task.before.join(","));
}
$tw.boot.log(s.join(" "));
// Execute task
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
task.startup();
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask();
} else {
task.startup(asyncTaskCallback);
return true;
}
}
taskIndex++;
}
return false;
};
/*
Returns true if we are running on one platforms specified in a task modules `platforms` array
*/
$tw.boot.doesTaskMatchPlatform = function(taskModule) {
var platforms = taskModule.platforms;
if(platforms) {
for(var t=0; t<platforms.length; t++) {
if((platforms[t] === "browser" && !$tw.browser) || (platforms[t] === "node" && !$tw.node)) {
return false;
}
}
}
return true;
};
$tw.boot.isStartupTaskEligible = function(taskModule) {
var t;
// Check that the platform is correct
if(!$tw.boot.doesTaskMatchPlatform(taskModule)) {
return false;
}
var name = taskModule.name,
remaining = $tw.boot.remainingStartupModules;
if(name) {
// Fail if this module is disabled
if($tw.boot.disabledStartupModules.indexOf(name) !== -1) {
return false;
}
// Check that no other outstanding tasks must be executed before this one
for(t=0; t<remaining.length; t++) {
var task = remaining[t];
if(task.before && task.before.indexOf(name) !== -1) {
if($tw.boot.doesTaskMatchPlatform(task) || (task.name && $tw.boot.disabledStartupModules.indexOf(name) !== -1)) {
return false;
}
}
}
}
// Check that all of the tasks that we must be performed after has been done
var after = taskModule.after;
if(after) {
for(t=0; t<after.length; t++) {
if(!$tw.boot.executedStartupModules[after[t]]) {
return false;
}
}
}
return true;
};
/////////////////////////// Main boot function to decrypt tiddlers and then startup
@@ -1667,15 +1881,13 @@ $tw.boot.boot = function() {
// Initialise crypto object
$tw.crypto = new $tw.utils.Crypto();
// Initialise password prompter
if($tw.browser) {
if($tw.browser && !$tw.node) {
$tw.passwordPrompt = new $tw.utils.PasswordPrompt();
}
// Preload any encrypted tiddlers
$tw.boot.decryptEncryptedTiddlers(function() {
// Startup
$tw.boot.startup({
readBrowserTiddlers: !!$tw.browser
});
$tw.boot.startup();
});
};

View File

@@ -16,13 +16,20 @@ var _bootprefix = (function($tw) {
"use strict";
$tw = $tw || {};
$tw = $tw || Object.create(null);
$tw.boot = $tw.boot || Object.create(null);
// Detect platforms
$tw.browser = typeof(window) !== "undefined" ? {} : null;
$tw.node = typeof(process) === "object" ? {} : null;
$tw.nodeWebKit = $tw.node && global.window && global.window.nwDispatcher ? {} : null;
// Set default boot tasks
$tw.boot.tasks = {
trapErrors: !!($tw.browser && !$tw.node),
readBrowserTiddlers: !!($tw.browser && !$tw.node)
};
/*
Information about each module is kept in an object with these members:
moduleType: type of module

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
title: $:/core/images/chevron-left
tags: $:/tags/Image
<svg class="tw-image-chevron-left tw-image-button" width="22pt" height="22pt" viewBox="0 0 128 128" version="1.1">
<g>
<path d="M97.7982405,98.1688105 L152.184015,43.4979042 C155.938662,39.7236635 155.938662,33.6043964 152.184015,29.8301557 C148.429583,26.0559364 142.342116,26.0559364 138.587684,29.8301557 L91.0000107,77.667222 L43.4123803,29.8301557 C39.6578195,26.0559364 33.5704813,26.0559364 29.8159206,29.8301557 C26.0613598,33.6043964 26.0613598,39.7236635 29.8159206,43.4979042 L84.2017595,98.1688105 C87.9563202,101.943051 94.0436798,101.943051 97.7982405,98.1688126 L97.7982405,98.1688105 Z" transform="translate(91.000000, 63.999491) rotate(-270.000000) translate(-91.000000, -63.999491) "></path>
<path d="M43.7982405,98.1688105 L98.1840153,43.4979042 C101.938662,39.7236635 101.938662,33.6043964 98.1840153,29.8301557 C94.4295828,26.0559364 88.3421164,26.0559364 84.5876838,29.8301557 L37.0000107,77.667222 L-10.5876197,29.8301557 C-14.3421805,26.0559364 -20.4295187,26.0559364 -24.1840794,29.8301557 C-27.9386402,33.6043964 -27.9386402,39.7236635 -24.1840794,43.4979042 L30.2017595,98.1688105 C33.9563202,101.943051 40.0436798,101.943051 43.7982405,98.1688126 L43.7982405,98.1688105 Z" transform="translate(37.000000, 63.999491) rotate(-270.000000) translate(-37.000000, -63.999491) "></path>
</g>
</svg>

View File

@@ -0,0 +1,9 @@
title: $:/core/images/chevron-right
tags: $:/tags/Image
<svg class="tw-image-chevron-right tw-image-button" width="22pt" height="22pt" viewBox="0 0 128 128">
<g>
<path d="M97.7982405,98.1688105 L152.184015,43.4979042 C155.938662,39.7236635 155.938662,33.6043964 152.184015,29.8301557 C148.429583,26.0559364 142.342116,26.0559364 138.587684,29.8301557 L91.0000107,77.667222 L43.4123803,29.8301557 C39.6578195,26.0559364 33.5704813,26.0559364 29.8159206,29.8301557 C26.0613598,33.6043964 26.0613598,39.7236635 29.8159206,43.4979042 L84.2017595,98.1688105 C87.9563202,101.943051 94.0436798,101.943051 97.7982405,98.1688126 L97.7982405,98.1688105 Z" transform="translate(91.000000, 63.999491) rotate(-90.000000) translate(-91.000000, -63.999491) "></path>
<path d="M43.7982405,98.1688105 L98.1840153,43.4979042 C101.938662,39.7236635 101.938662,33.6043964 98.1840153,29.8301557 C94.4295828,26.0559364 88.3421164,26.0559364 84.5876838,29.8301557 L37.0000107,77.667222 L-10.5876197,29.8301557 C-14.3421805,26.0559364 -20.4295187,26.0559364 -24.1840794,29.8301557 C-27.9386402,33.6043964 -27.9386402,39.7236635 -24.1840794,43.4979042 L30.2017595,98.1688105 C33.9563202,101.943051 40.0436798,101.943051 43.7982405,98.1688126 L43.7982405,98.1688105 Z" transform="translate(37.000000, 63.999491) rotate(-90.000000) translate(-37.000000, -63.999491) "></path>
</g>
</svg>

View File

@@ -0,0 +1,4 @@
title: $:/core/images/right-arrow
tags: $:/tags/Image
<svg class="tw-image-right-arrow tw-image-button" width="22pt" height="22pt" viewBox="0 0 128 128"><path d="M72.7982405,98.6541105 L127.184015,43.9832042 C130.938662,40.2089635 130.938662,34.0896964 127.184015,30.3154557 C123.429583,26.5412364 117.342116,26.5412364 113.587684,30.3154557 L66.0000107,78.152522 L18.4123803,30.3154557 C14.6578195,26.5412364 8.57048132,26.5412364 4.81592057,30.3154557 C1.06135981,34.0896964 1.06135981,40.2089635 4.81592057,43.9832042 L59.2017595,98.6541105 C62.9563202,102.428351 69.0436798,102.428351 72.7982405,98.6541126 L72.7982405,98.6541105 Z" transform="translate(66.000000, 64.484791) rotate(-90.000000) translate(-66.000000, -64.484791) "/></svg>

View File

@@ -0,0 +1,26 @@
title: $:/language/Buttons/
AdvancedSearch/Caption: advanced search
AdvancedSearch/Hint: Advanced search
Cancel/Caption: cancel
Cancel/Hint: Cancel editing this tiddler
Close/Caption: close
Close/Hint: Close this tiddler
ControlPanel/Caption: control panel
ControlPanel/Hint: Open control panel
Delete/Caption: delete
Delete/Hint: Delete this tiddler
Edit/Caption: edit
Edit/Hint: Edit this tiddler
Info/Caption: info
Info/Hint: Show information for this tiddler
NewTiddler/Caption: new tiddler
NewTiddler/Hint: Create a new tiddler
Save/Caption: save
Save/Hint: Save this tiddler
SaveWiki/Caption: save changes
SaveWiki/Hint: Save changes
HideSideBar/Caption: hide sidebar
HideSideBar/Hint: Hide sidebar
ShowSideBar/Caption: show sidebar
ShowSideBar/Hint: Show sidebar

View File

@@ -1,9 +1,24 @@
title: $:/language/ControlPanel/
Advanced/Caption: Advanced
Advanced/EditorTypes/Caption: Editor Types
Advanced/EditorTypes/Editor/Caption: Editor
Advanced/EditorTypes/Hint: These tiddlers determine which editor is used to edit specific tiddler types.
Advanced/EditorTypes/Type/Caption: Type
Advanced/Hint: Internal information about this TiddlyWiki
Advanced/LoadedModules/Caption: Loaded Modules
Advanced/LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
Advanced/Settings/Caption: Settings
Advanced/Settings/Hint: These advanced settings let you customise the behaviour of TiddlyWiki.
Advanced/Settings/NavigationAddressBar/Caption: Navigation Address Bar
Advanced/Settings/NavigationAddressBar/Hint: Behaviour of the browser address bar when navigating to a tiddler:
Advanced/Settings/NavigationAddressBar/No/Description: Do not update the address bar
Advanced/Settings/NavigationAddressBar/Permalink/Description: Include the target tiddler
Advanced/Settings/NavigationAddressBar/Permaview/Description: Include the target tiddler and the current story sequence
Advanced/Settings/NavigationHistory/Caption: Navigation History
Advanced/Settings/NavigationHistory/Hint: Update browser history when navigating to a tiddler:
Advanced/Settings/NavigationHistory/No/Description: Do not update history
Advanced/Settings/NavigationHistory/Yes/Description: Update history
Advanced/TiddlerFields/Caption: Tiddler Fields
Advanced/TiddlerFields/Hint: This is the full set of TiddlerFields in use in this wiki (including system tiddlers but excluding shadow tiddlers).
Appearance/Caption: Appearance

View File

@@ -1,7 +1,6 @@
title: $:/language/Docs/ModuleTypes/
animation: Animations that may be used with the RevealWidget.
browser-startup: Startup functions that are only executed in the browser.
command: Commands that can be executed under Node.js.
config: Data to be inserted into `$tw.config`.
filteroperator: Individual filter operator methods.

View File

@@ -1,5 +1,6 @@
title: $:/language/EditTemplate/
Body/External/Hint: This is an external tiddler stored outside of the main TiddlyWiki file. You can edit the tags and fields but cannot directly edit the content itself
Body/Hint: Use [[wiki text|http://tiddlywiki.com/static/WikiText.html]] to add formatting, images, and dynamic features
Body/Placeholder: Type the text for this tiddler
Body/Preview/Button/Hide: hide preview
@@ -8,6 +9,8 @@ Fields/Add/Button: add
Fields/Add/Name/Placeholder: field name
Fields/Add/Prompt: Add a new field:
Fields/Add/Value/Placeholder: field value
Shadow/Warning: This is a shadow tiddler. Any changes will override the default version
Shadow/OverriddenWarning: This is a modified shadow tiddler. You can revert to the default version by deleting this tiddler
Tags/Add/Button: add
Tags/Add/Placeholder: tag name
Type/Placeholder: content type

View File

@@ -1,5 +1,6 @@
title: $:/language/Docs/Fields/
_canonical_uri: The full URI of an external image tiddler
bag: The name of the bag from which a tiddler came
caption: The text to be displayed on a tab or button
color: The CSS color value associated with a tiddler

View File

@@ -0,0 +1,11 @@
title: $:/language/Help/build
description: Automatically run configured commands
Build the specified build targets for the current wiki. If no build targets are specified then all available targets will be built.
```
--build <target> [<target> ...]
```
Build targets are defined in the `tiddlywiki.info` file of a wiki folder.

View File

@@ -0,0 +1,8 @@
title: $:/language/Help/clearpassword
description: Clear a password for subsequent crypto operations
Clear the password for subsequent crypto operations
```
--clearpassword
```

View File

@@ -0,0 +1,10 @@
title: $:/language/Help/output
description: Set the base output directory for subsequent commands
Sets the base output directory for subsequent commands. The default output directory is the `output` subdirectory of the edition directory.
```
--output <pathname>
```
If the specified pathname is relative then it is resolved relative to the current working directory.

View File

@@ -6,3 +6,7 @@ Render an individual tiddler as a specified ContentType, defaults to `text/html`
```
--rendertiddler <title> <filename> [<type>]
```
By default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
Any missing directories in the path to the filename are automatically created.

View File

@@ -12,3 +12,7 @@ For example:
```
--rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain
```
By default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
Any files in the target directory are deleted. The target directory is recursively created if it is missing.

View File

@@ -6,3 +6,7 @@ Saves an individual tiddler in its raw text or binary format to the specified fi
```
--savetiddler <title> <filename>
```
By default, the filename is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
Any missing directories in the path to the filename are automatically created.

View File

@@ -0,0 +1,12 @@
title: $:/language/Help/savetiddlers
description: Saves a group of raw tiddlers to a directory
Saves a group of tiddlers in their raw text or binary format to the specified directory.
```
--savetiddlers <filter> <pathname>
```
By default, the pathname is resolved relative to the `output` subdirectory of the edition directory. The `--output` command can be used to direct output to a different directory.
Any missing directories in the pathname are automatically created.

View File

@@ -6,7 +6,7 @@ The server built in to TiddlyWiki5 is very simple. Although compatible with Tidd
At the root, it serves a rendering of a specified tiddler. Away from the root, it serves individual tiddlers encoded in JSON, and supports the basic HTTP operations for `GET`, `PUT` and `DELETE`.
```
--server <port> <roottiddler> <rendertype> <servetype> <username> <password> <host>
--server <port> <roottiddler> <rendertype> <servetype> <username> <password> <host> <pathprefix>
```
The parameters are:
@@ -18,6 +18,7 @@ The parameters are:
* ''username'' - the default username for signing edits
* ''password'' - optional password for basic authentication
* ''host'' - optional hostname to serve from (defaults to "127.0.0.1" aka "localhost")
* ''pathprefix'' - optional prefix for paths
If the password parameter is specified then the browser will prompt the user for the username and password. Note that the password is transmitted in plain text so this implementation isn't suitable for general use.

View File

@@ -0,0 +1,18 @@
title: $:/language/Help/setfield
description: Prepares external tiddlers for use
//Note that this command is experimental and may change or be replaced during the TiddlyWiki version 5 beta//
Sets the specified field of a group of tiddlers to the result of wikifying a template tiddler with the `currentTiddler` variable set to the tiddler.
```
--setfield <filter> <fieldname> <templatetitle> <rendertype>
```
The parameters are:
* ''filter'' - filter identifying the tiddlers to be affected
* ''fieldname'' - the field to modify (defaults to "text")
* ''templatetitle'' - the tiddler to wikify into the specified field. If blank or missing then the specified field is deleted
* ''type'' - the text type to render (defaults to "text/plain"; "text/html" can be used to include HTML tags)

View File

@@ -1,12 +1,14 @@
title: $:/language/
BinaryWarning/Prompt: This tiddler contains binary data
ClassicWarning/Hint: This tiddler is written in TiddlyWiki Classic wiki text format, which is not fully compatible with TiddlyWiki version 5. See http://tiddlywiki.com/static/Upgrading.html for more details.
ClassicWarning/Upgrade/Caption: upgrade
CloseAll/Button: close all
ConfirmCancelTiddler: Do you wish to discard changes to the tiddler "<$text text=<<title>>/>"?
ConfirmDeleteTiddler: Do you wish to delete the tiddler "<$text text=<<title>>/>"?
ConfirmOverwriteTiddler: Do you wish to overwrite the tiddler "<$text text=<<title>>/>"?
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters and the characters underscore (`_`), hyphen (`-`) and period (`.`)
ConfirmEditShadowTiddler: You are about to edit a ShadowTiddler. Any changes will override the default system making future upgrades non-trivial. Are you sure you want to edit "<$text text=<<title>>/>"?
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)
MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" - click {{$:/core/images/edit-button}} to create
RecentChanges/DateFormat: DDth MMM YYYY
RelativeDate/Future/Days: <<period>> days from now

View File

@@ -1,10 +1,15 @@
title: $:/language/Search/
Advanced/Matches: //<small><$count filter={{$:/temp/advancedsearch}}/> matches</small>//
Filter/Caption: Filter
Filter/Hint: Search via a [[filter expression|http://tiddlywiki.com/static/TiddlerFilters.html]]
Filter/Matches: //<small><$count filter={{$:/temp/advancedsearch}}/> matches</small>//
Matches: //<small><$count filter="[!is[system]search{$:/temp/search}]"/> matches</small>//
Shadows/Caption: Shadows
Shadows/Hint: Search for shadow tiddlers
Shadows/Matches: //<small><$count filter="[all[shadows]search{$:/temp/advancedsearch}]"/> matches</small>//
Standard/Caption: Standard
Standard/Hint: Search for standard tiddlers
Standard/Matches: //<small><$count filter="[!is[system]search{$:/temp/advancedsearch}]"/> matches</small>//
System/Caption: System
System/Hint: Search for system tiddlers
System/Matches: //<small><$count filter="[is[system]search{$:/temp/advancedsearch}]"/> matches</small>//

View File

@@ -1,6 +1,7 @@
title: $:/language/SideBar/
All/Caption: All
Contents/Caption: Contents
Drafts/Caption: Drafts
Missing/Caption: Missing
More/Caption: More

View File

@@ -0,0 +1,4 @@
title: $:/language/Docs/Types/application/javascript
description: JavaScript code
name: application/javascript
group: Developer

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/application/json
description: JSON data
name: application/json
group: Developer

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/application/x-tiddler-dictionary
description: Data dictionary
name: application/x-tiddler-dictionary
group: Developer

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/image/gif
description: GIF image
name: image/gif
group: Image

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/image/jpeg
description: JPEG image
name: image/jpeg
group: Image

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/image/png
description: PNG image
name: image/png
group: Image

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/image/svg+xml
description: Structured Vector Graphics image
name: image/svg+xml
group: Image

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/image/x-icon
description: ICO format icon file
name: image/x-icon
group: Image

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/text/css
description: Static stylesheet
name: text/css
group: Developer

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/text/html
description: HTML markup
name: text/html
group: Text

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/text/plain
description: Plain text
name: text/plain
group: Text

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/text/vnd.tiddlywiki
description: TiddlyWiki version 5 wikitext
description: TiddlyWiki 5
name: text/vnd.tiddlywiki
group: Text

View File

@@ -1,3 +1,4 @@
title: $:/language/Docs/Types/text/x-tiddlywiki
description: TiddlyWiki Classic wikitext
description: TiddlyWiki Classic
name: text/x-tiddlywiki
group: Text

View File

@@ -20,11 +20,20 @@ Parse a sequence of commands
callback: a callback invoked as callback(err) where err is null if there was no error
*/
var Commander = function(commandTokens,callback,wiki,streams) {
var path = require("path");
this.commandTokens = commandTokens;
this.nextToken = 0;
this.callback = callback;
this.wiki = wiki;
this.streams = streams;
this.outputPath = path.resolve($tw.boot.wikiPath,$tw.config.wikiOutputSubDir);
};
/*
Add a string of tokens to the command queue
*/
Commander.prototype.addCommandTokens = function(commandTokens) {
Array.prototype.push.apply(this.commandTokens,commandTokens);
};
/*

View File

@@ -0,0 +1,52 @@
/*\
title: $:/core/modules/commands/build.js
type: application/javascript
module-type: command
Command to build a build target
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "build",
synchronous: true
};
var Command = function(params,commander) {
this.params = params;
this.commander = commander;
};
Command.prototype.execute = function() {
// Get the build targets defined in the wiki
var buildTargets = $tw.boot.wikiInfo.build;
if(!buildTargets) {
return "No build targets defined"
}
// Loop through each of the specified targets
var targets;
if(this.params.length > 0) {
targets = this.params;
} else {
targets = Object.keys(buildTargets);
}
for(var targetIndex=0; targetIndex<targets.length; targetIndex++) {
var target = targets[targetIndex],
commands = buildTargets[target];
if(!commands) {
return "Build target '" + target + "' not found";
}
// Add the commands to the queue
this.commander.addCommandTokens(commands);
}
return null;
};
exports.Command = Command;
})();

View File

@@ -0,0 +1,33 @@
/*\
title: $:/core/modules/commands/clearpassword.js
type: application/javascript
module-type: command
Clear password for crypto operations
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "clearpassword",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
$tw.crypto.setPassword(null);
return null;
};
exports.Command = Command;
})();

View File

@@ -34,7 +34,7 @@ Command.prototype.execute = function() {
for(var editionIndex=0; editionIndex<editions.length; editionIndex++) {
var editionName = editions[editionIndex];
// Check the edition exists
var editionPath = path.resolve($tw.boot.corePath,$tw.config.editionsPath) + path.sep + editionName;
var editionPath = $tw.findLibraryItem(editionName,$tw.getLibraryItemSearchPaths($tw.config.editionsPath,$tw.config.editionsEnvVar));
if(!$tw.utils.isDirectory(editionPath)) {
return "Edition '" + editionName + "' not found";
}

View File

@@ -0,0 +1,38 @@
/*\
title: $:/core/modules/commands/output.js
type: application/javascript
module-type: command
Command to set the default output location (defaults to current working directory)
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "output",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
var fs = require("fs"),
path = require("path");
if(this.params.length < 1) {
return "Missing output path";
}
this.commander.outputPath = path.resolve(process.cwd(),this.params[0]);
return null;
};
exports.Command = Command;
})();

View File

@@ -31,8 +31,9 @@ Command.prototype.execute = function() {
fs = require("fs"),
path = require("path"),
title = this.params[0],
filename = this.params[1],
filename = path.resolve(this.commander.outputPath,this.params[1]),
type = this.params[2] || "text/html";
$tw.utils.createFileDirectories(filename);
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
self.callback(err);
});

View File

@@ -35,10 +35,12 @@ Command.prototype.execute = function() {
wiki = this.commander.wiki,
filter = this.params[0],
template = this.params[1],
pathname = this.params[2],
pathname = path.resolve(this.commander.outputPath,this.params[2]),
type = this.params[3] || "text/html",
extension = this.params[4] || ".html",
tiddlers = wiki.filterTiddlers(filter);
$tw.utils.deleteDirectory(pathname);
$tw.utils.createDirectory(pathname);
$tw.utils.each(tiddlers,function(title) {
var parser = wiki.parseTiddler(template),
widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});

View File

@@ -31,10 +31,11 @@ Command.prototype.execute = function() {
fs = require("fs"),
path = require("path"),
title = this.params[0],
filename = this.params[1],
filename = path.resolve(this.commander.outputPath,this.params[1]),
tiddler = this.commander.wiki.getTiddler(title),
type = tiddler.fields.type || "text/vnd.tiddlywiki",
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"};
$tw.utils.createFileDirectories(filename);
fs.writeFile(filename,tiddler.fields.text,contentTypeInfo.encoding,function(err) {
self.callback(err);
});

View File

@@ -0,0 +1,53 @@
/*\
title: $:/core/modules/commands/savetiddlers.js
type: application/javascript
module-type: command
Command to save several tiddlers to a folder of files
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "savetiddlers",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filename";
}
var self = this,
fs = require("fs"),
path = require("path"),
wiki = this.commander.wiki,
filter = this.params[0],
pathname = path.resolve(this.commander.outputPath,this.params[1]),
tiddlers = wiki.filterTiddlers(filter);
$tw.utils.deleteDirectory(pathname);
$tw.utils.createDirectory(pathname);
$tw.utils.each(tiddlers,function(title) {
var tiddler = self.commander.wiki.getTiddler(title),
type = tiddler.fields.type || "text/vnd.tiddlywiki",
contentTypeInfo = $tw.config.contentTypeInfo[type] || {encoding: "utf8"},
filename = path.resolve(pathname,encodeURIComponent(title));
fs.writeFileSync(filename,tiddler.fields.text,contentTypeInfo.encoding);
});
return null;
};
exports.Command = Command;
})();

View File

@@ -50,10 +50,22 @@ SimpleServer.prototype.addRoute = function(route) {
};
SimpleServer.prototype.findMatchingRoute = function(request,state) {
var pathprefix = this.get("pathprefix") || "";
for(var t=0; t<this.routes.length; t++) {
var potentialRoute = this.routes[t],
pathRegExp = potentialRoute.path,
match = potentialRoute.path.exec(state.urlInfo.pathname);
pathname = state.urlInfo.pathname,
match;
if(pathprefix) {
if(pathname.substr(0,pathprefix.length) === pathprefix) {
pathname = pathname.substr(pathprefix.length);
match = potentialRoute.path.exec(pathname);
} else {
match = false;
}
} else {
match = potentialRoute.path.exec(pathname);
}
if(match && request.method === potentialRoute.method) {
state.params = [];
for(var p=1; p<match.length; p++) {
@@ -161,7 +173,8 @@ var Command = function(params,commander,callback) {
state.wiki.addTiddler(new $tw.Tiddler(state.wiki.getCreationFields(),fields,{title: title}));
var changeCount = state.wiki.getChangeCount(title).toString();
response.writeHead(204, "OK",{
Etag: "\"default/" + encodeURIComponent(title) + "/" + changeCount + ":\""
Etag: "\"default/" + encodeURIComponent(title) + "/" + changeCount + ":\"",
"Content-Type": "text/plain"
});
response.end();
}
@@ -172,7 +185,9 @@ var Command = function(params,commander,callback) {
handler: function(request,response,state) {
var title = decodeURIComponent(state.params[0]);
state.wiki.deleteTiddler(title);
response.writeHead(204, "OK");
response.writeHead(204, "OK", {
"Content-Type": "text/plain"
});
response.end();
}
});
@@ -269,13 +284,15 @@ Command.prototype.execute = function() {
serveType = this.params[3] || "text/html",
username = this.params[4],
password = this.params[5],
host = this.params[6] || "127.0.0.1";
host = this.params[6] || "127.0.0.1",
pathprefix = this.params[7];
this.server.set({
rootTiddler: rootTiddler,
renderType: renderType,
serveType: serveType,
username: username,
password: password
password: password,
pathprefix: pathprefix
});
this.server.listen(port,host);
console.log("Serving on " + host + ":" + port);

View File

@@ -0,0 +1,58 @@
/*\
title: $:/core/modules/commands/setfield.js
type: application/javascript
module-type: command
Command to modify selected tiddlers to set a field to the text of a template tiddler that has been wikified with the selected tiddler as the current tiddler.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var widget = require("$:/core/modules/widgets/widget.js");
exports.info = {
name: "setfield",
synchronous: true
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 4) {
return "Missing parameters";
}
var self = this,
wiki = this.commander.wiki,
filter = this.params[0],
fieldname = this.params[1] || "text",
templatetitle = this.params[2],
rendertype = this.params[3] || "text/plain",
tiddlers = wiki.filterTiddlers(filter);
$tw.utils.each(tiddlers,function(title) {
var parser = wiki.parseTiddler(templatetitle),
newFields = {},
tiddler = wiki.getTiddler(title);
if(parser) {
var widgetNode = wiki.makeWidget(parser,{variables: {currentTiddler: title}});
var container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
newFields[fieldname] = rendertype === "text/html" ? container.innerHTML : container.textContent;
} else {
newFields[fieldname] = undefined;
}
wiki.addTiddler(new $tw.Tiddler(tiddler,newFields));
});
return null;
};
exports.Command = Command;
})();

View File

@@ -24,6 +24,8 @@ var Command = function(params,commander) {
Command.prototype.execute = function() {
this.commander.verbose = true;
// Output the boot message log
this.commander.streams.output.write("Boot log:\n " + $tw.boot.logMessages.join("\n ") + "\n");
return null; // No error
};

View File

@@ -51,13 +51,13 @@ var parseTiddlerDiv = function(text /* [,fields] */) {
// Extract the text
result.text = text.substring(match.index + match[0].length,endMatch.index);
// Process the attributes
var attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi,
var attrRegExp = /\s*([^=\s]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/gi,
attrMatch;
do {
attrMatch = attrRegExp.exec(match[1]);
if(attrMatch) {
var name = attrMatch[1];
var value = attrMatch[2];
var value = attrMatch[2] !== undefined ? attrMatch[2] : attrMatch[3];
result[name] = value;
}
} while(attrMatch);

View File

@@ -149,22 +149,22 @@ exports.getFilterOperators = function() {
return this.filterOperators;
};
exports.filterTiddlers = function(filterString,currTiddlerTitle,source) {
exports.filterTiddlers = function(filterString,widget,source) {
var fn = this.compileFilter(filterString);
return fn.call(this,source,currTiddlerTitle);
return fn.call(this,source,widget);
};
/*
Compile a filter into a function with the signature fn(source,currTiddlerTitle) where:
Compile a filter into a function with the signature fn(source,widget) where:
source: an iterator function for the source tiddlers, called source(iterator), where iterator is called as iterator(tiddler,title)
currTiddlerTitle: the optional name of the current tiddler
widget: an optional widget node for retrieving the current tiddler etc.
*/
exports.compileFilter = function(filterString) {
var filterParseTree;
try {
filterParseTree = this.parseFilter(filterString);
} catch(e) {
return function(source,currTiddlerTitle) {
return function(source,widget) {
return ["Filter error: " + e];
};
}
@@ -176,9 +176,10 @@ exports.compileFilter = function(filterString) {
var self = this;
$tw.utils.each(filterParseTree,function(operation) {
// Create a function for the chain of operators in the operation
var operationSubFunction = function(source,currTiddlerTitle) {
var operationSubFunction = function(source,widget) {
var accumulator = source,
results = [];
results = [],
currTiddlerTitle = widget && widget.getVariable("currentTiddler");
$tw.utils.each(operation.operators,function(operator) {
var operand = operator.operand,
operatorFunction;
@@ -200,35 +201,47 @@ exports.compileFilter = function(filterString) {
regexp: operator.regexp
},{
wiki: self,
currTiddlerTitle: currTiddlerTitle
widget: widget
});
accumulator = self.makeTiddlerIterator(results);
if($tw.utils.isArray(results)) {
accumulator = self.makeTiddlerIterator(results);
} else {
accumulator = results;
}
});
return results;
if($tw.utils.isArray(results)) {
return results;
} else {
var resultArray = [];
results(function(tiddler,title) {
resultArray.push(title);
});
return resultArray;
}
};
// Wrap the operator functions in a wrapper function that depends on the prefix
operationFunctions.push((function() {
switch(operation.prefix || "") {
case "": // No prefix means that the operation is unioned into the result
return function(results,source,currTiddlerTitle) {
$tw.utils.pushTop(results,operationSubFunction(source,currTiddlerTitle));
return function(results,source,widget) {
$tw.utils.pushTop(results,operationSubFunction(source,widget));
};
case "-": // The results of this operation are removed from the main result
return function(results,source,currTiddlerTitle) {
$tw.utils.removeArrayEntries(results,operationSubFunction(source,currTiddlerTitle));
return function(results,source,widget) {
$tw.utils.removeArrayEntries(results,operationSubFunction(source,widget));
};
case "+": // This operation is applied to the main results so far
return function(results,source,currTiddlerTitle) {
return function(results,source,widget) {
// This replaces all the elements of the array, but keeps the actual array so that references to it are preserved
source = self.makeTiddlerIterator(results);
results.splice(0,results.length);
$tw.utils.pushTop(results,operationSubFunction(source,currTiddlerTitle));
$tw.utils.pushTop(results,operationSubFunction(source,widget));
};
}
})());
});
// Return a function that applies the operations to a source iterator of tiddler titles
return $tw.perf.measure("filter",function filterFunction(source,currTiddlerTitle) {
return $tw.perf.measure("filter",function filterFunction(source,widget) {
if(!source) {
source = self.each;
} else if(typeof source === "object") { // Array or hashmap
@@ -236,7 +249,7 @@ exports.compileFilter = function(filterString) {
}
var results = [];
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,currTiddlerTitle);
operationFunction(results,source,widget);
});
return results;
});

View File

@@ -0,0 +1,31 @@
/*\
title: $:/core/modules/filters/after.js
type: application/javascript
module-type: filteroperator
Filter operator returning the tiddler from the current list that is after the tiddler named in the operand.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.after = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(title);
});
var index = results.indexOf(operator.operand);
if(index === -1 || index > (results.length - 2)) {
return [];
} else {
return [results[index + 1]];
}
};
})();

View File

@@ -5,7 +5,7 @@ module-type: filteroperator
Filter operator for selecting tiddlers
[all[tiddlers+shadows]]
[all[shadows+tiddlers]]
\*/
(function(){
@@ -33,6 +33,17 @@ exports.all = function(source,operator,options) {
// Cycle through the suboperators accumulating their results
var results = [],
subops = operator.operand.split("+");
// Check for common optimisations
if(subops.length === 1 && subops[0] === "tiddlers") {
return options.wiki.each;
} else if(subops.length === 1 && subops[0] === "shadows") {
return options.wiki.eachShadow;
} else if(subops.length === 2 && subops[0] === "tiddlers" && subops[1] === "shadows") {
return options.wiki.eachTiddlerPlusShadows;
} else if(subops.length === 2 && subops[0] === "shadows" && subops[1] === "tiddlers") {
return options.wiki.eachShadowPlusTiddlers;
}
// Do it the hard way
for(var t=0; t<subops.length; t++) {
var subop = allFilterOperators[subops[t]];
if(subop) {

View File

@@ -16,8 +16,9 @@ Filter function for [all[current]]
Export our filter function
*/
exports.current = function(source,prefix,options) {
if(options.currTiddlerTitle) {
return [options.currTiddlerTitle];
var currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler");
if(currTiddlerTitle) {
return [currTiddlerTitle];
} else {
return [];
}

View File

@@ -0,0 +1,31 @@
/*\
title: $:/core/modules/filters/before.js
type: application/javascript
module-type: filteroperator
Filter operator returning the tiddler from the current list that is before the tiddler named in the operand.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.before = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(title);
});
var index = results.indexOf(operator.operand);
if(index <= 0) {
return [];
} else {
return [results[index - 1]];
}
};
})();

View File

@@ -0,0 +1,31 @@
/*\
title: $:/core/modules/filters/get.js
type: application/javascript
module-type: filteroperator
Filter operator for replacing tiddler titles by the value of the field specified in the operand.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.get = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
if(tiddler) {
var value = tiddler.getFieldString(operator.operand);
if(value) {
results.push(value);
}
}
});
return results;
};
})();

View File

@@ -16,16 +16,17 @@ Filter function for [is[current]]
Export our filter function
*/
exports.current = function(source,prefix,options) {
var results = [];
var results = [],
currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler");
if(prefix === "!") {
source(function(tiddler,title) {
if(title !== options.currTiddlerTitle) {
if(title !== currTiddlerTitle) {
results.push(title);
}
});
} else {
source(function(tiddler,title) {
if(title === options.currTiddlerTitle) {
if(title === currTiddlerTitle) {
results.push(title);
}
});

View File

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

View File

@@ -18,7 +18,8 @@ Export our filter function
exports.list = function(source,operator,options) {
var results = [],
tr = $tw.utils.parseTextReference(operator.operand),
list = options.wiki.getTiddlerList(tr.title || options.currTiddlerTitle,tr.field,tr.index);
currTiddlerTitle = options.widget && options.widget.getVariable("currentTiddler"),
list = options.wiki.getTiddlerList(tr.title || currTiddlerTitle,tr.field,tr.index);
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(list.indexOf(title) === -1) {

View File

@@ -16,9 +16,10 @@ Filter operator returning all tiddlers that have the selected tiddlers in a list
Export our filter function
*/
exports.listed = function(source,operator,options) {
var results = [];
var field = operator.operand || "list",
results = [];
source(function(tiddler,title) {
$tw.utils.pushTop(results,options.wiki.findListingsOfTiddler(title));
$tw.utils.pushTop(results,options.wiki.findListingsOfTiddler(title,field));
});
return results;
};

View File

@@ -25,10 +25,8 @@ exports.untagged = function(source,operator,options) {
});
} else {
source(function(tiddler,title) {
if(tiddler) {
if(!tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
$tw.utils.pushTop(results,title);
}
if(!tiddler || !tiddler.hasField("tags") || ($tw.utils.isArray(tiddler.fields.tags) && tiddler.fields.tags.length === 0)) {
$tw.utils.pushTop(results,title);
}
});
}

View File

@@ -15,7 +15,7 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
var CsvParser = function(type,text,options) {
// Table framework
this.tree = [{
"type": "element", "tag": "$scrollable", "children": [{
"type": "scrollable", "children": [{
"type": "element", "tag": "table", "children": [{
"type": "element", "tag": "tbody", "children": []
}], "attributes": {

View File

@@ -13,9 +13,18 @@ The HTML parser displays text as raw HTML
"use strict";
var HtmlParser = function(type,text,options) {
var src;
if(options._canonical_uri) {
src = options._canonical_uri;
} else if(text) {
src = "data:text/html," + encodeURIComponent(text);
}
this.tree = [{
type: "raw",
html: text
type: "element",
tag: "iframe",
attributes: {
src: {type: "string", value: src}
}
}];
};

View File

@@ -19,7 +19,12 @@ var ImageParser = function(type,text,options) {
attributes: {}
},
src;
if(text) {
if(options._canonical_uri) {
element.attributes.src = {type: "string", value: options._canonical_uri};
if(type === "application/pdf" || type === ".pdf") {
element.tag = "embed";
}
} else if(text) {
if(type === "application/pdf" || type === ".pdf") {
element.attributes.src = {type: "string", value: "data:application/pdf;base64," + text};
element.tag = "embed";

View File

@@ -0,0 +1,272 @@
/*\
title: $:/core/modules/utils/parseutils.js
type: application/javascript
module-type: utils
Utility functions concerned with parsing text into tokens.
Most functions have the following pattern:
* The parameters are:
** `source`: the source string being parsed
** `pos`: the current parse position within the string
** Any further parameters are used to identify the token that is being parsed
* The return value is:
** null if the token was not found at the specified position
** an object representing the token with the following standard fields:
*** `type`: string indicating the type of the token
*** `start`: start position of the token in the source string
*** `end`: end position of the token in the source string
*** Any further fields required to describe the token
The exception is `skipWhiteSpace`, which just returns the position after the whitespace.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Look for a whitespace token. Returns null if not found, otherwise returns {type: "whitespace", start:, end:,}
*/
exports.parseWhiteSpace = function(source,pos) {
var node = {
type: "whitespace",
start: pos
};
var re = /(\s)+/g;
re.lastIndex = pos;
var match = re.exec(source);
if(match && match.index === pos) {
node.end = pos + match[0].length;
return node;
}
return null;
};
/*
Convenience wrapper for parseWhiteSpace. Returns the position after the whitespace
*/
exports.skipWhiteSpace = function(source,pos) {
var whitespace = $tw.utils.parseWhiteSpace(source,pos);
if(whitespace) {
return whitespace.end;
}
return pos;
};
/*
Look for a given string token. Returns null if not found, otherwise returns {type: "token", value:, start:, end:,}
*/
exports.parseTokenString = function(source,pos,token) {
var match = source.indexOf(token,pos) === pos;
if(match) {
return {
type: "token",
value: token,
start: pos,
end: pos + token.length
};
}
return null;
};
/*
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
*/
exports.parseTokenRegExp = function(source,pos,reToken) {
var node = {
type: "regexp",
start: pos
};
reToken.lastIndex = pos;
node.match = reToken.exec(source);
if(node.match && node.match.index === pos) {
node.end = pos + node.match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a string literal. Returns null if not found, otherwise returns {type: "string", value:, start:, end:,}
*/
exports.parseStringLiteral = function(source,pos) {
var node = {
type: "string",
start: pos
};
var reString = /(?:"""([\s\S]*?)"""|"([^"]*)")|(?:'([^']*)')/g;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
node.value = match[1] !== undefined ? match[1] :(
match[2] !== undefined ? match[2] : match[3]
);
node.end = pos + match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
exports.parseMacroParameter = function(source,pos) {
var node = {
type: "macro-parameter",
start: pos
};
// Define our regexp
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the parameter
var token = $tw.utils.parseTokenRegExp(source,pos,reMacroParameter);
if(!token) {
return null;
}
pos = token.end;
// Get the parameter details
node.value = token.match[2] !== undefined ? token.match[2] : (
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
token.match[6] !== undefined ? token.match[6] : (
""
)
)
)
)
);
if(token.match[1]) {
node.name = token.match[1];
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {
type: "macrocall",
start: pos,
params: []
};
// Define our regexps
var reMacroName = /([^\s>"'=]+)/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double less than sign
var token = $tw.utils.parseTokenString(source,pos,"<<");
if(!token) {
return null;
}
pos = token.end;
// Get the macro name
var name = $tw.utils.parseTokenRegExp(source,pos,reMacroName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Process parameters
var parameter = $tw.utils.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = $tw.utils.parseMacroParameter(source,pos);
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double greater than sign
token = $tw.utils.parseTokenString(source,pos,">>");
if(!token) {
return null;
}
pos = token.end;
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the attribute name
var name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for an equals sign
var token = $tw.utils.parseTokenString(source,pos,"=");
if(token) {
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
// Look for an indirect value
var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = $tw.utils.parseMacroInvocation(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
node.type = "string";
node.value = "true";
}
}
}
}
} else {
node.type = "string";
node.value = "true";
}
// Update the end position
node.end = pos;
return node;
};
})();

View File

@@ -14,12 +14,11 @@ The plain text parser processes blocks of source text into a degenerate parse tr
var TextParser = function(type,text,options) {
this.tree = [{
type: "element",
tag: "pre",
children: [{
type: "text",
text: text
}]
type: "codeblock",
attributes: {
code: {type: "string", value: text},
language: {type: "string", value: type}
}
}];
};

View File

@@ -46,8 +46,7 @@ exports.parse = function() {
}
// Return the $codeblock widget
return [{
type: "element",
tag: "$codeblock",
type: "codeblock",
attributes: {
code: {type: "string", value: text},
language: {type: "string", value: this.match[1]}

View File

@@ -40,8 +40,7 @@ exports.parse = function() {
classes = this.match[5];
// Return the list widget
var node = {
type: "element",
tag: "$list",
type: "list",
attributes: {
filter: {type: "string", value: filter}
},

View File

@@ -40,8 +40,7 @@ exports.parse = function() {
classes = this.match[5];
// Return the list widget
var node = {
type: "element",
tag: "$list",
type: "list",
attributes: {
filter: {type: "string", value: filter}
}

View File

@@ -48,7 +48,7 @@ exports.parse = function() {
// Advance the parser position to past the tag
this.parser.pos = tag.end;
// Check for an immediately following double linebreak
var hasLineBreak = !tag.isSelfClosing && !!this.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
var hasLineBreak = !tag.isSelfClosing && !!$tw.utils.parseTokenRegExp(this.parser.source,this.parser.pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
// Set whether we're in block mode
tag.isBlock = this.is.block || hasLineBreak;
// Parse the body if we need to
@@ -71,244 +71,7 @@ exports.parse = function() {
};
/*
Look for a whitespace token. Returns null if not found, otherwise returns {type: "whitespace", start:, end:,}
*/
exports.parseWhiteSpace = function(source,pos) {
var node = {
type: "whitespace",
start: pos
};
var re = /(\s)+/g;
re.lastIndex = pos;
var match = re.exec(source);
if(match && match.index === pos) {
node.end = pos + match[0].length;
return node;
}
return null;
};
/*
Convenience wrapper for parseWhiteSpace
*/
exports.skipWhiteSpace = function(source,pos) {
var whitespace = this.parseWhiteSpace(source,pos);
if(whitespace) {
return whitespace.end;
}
return pos;
};
/*
Look for a given string token. Returns null if not found, otherwise returns {type: "token", value:, start:, end:,}
*/
exports.parseTokenString = function(source,pos,token) {
var match = source.indexOf(token,pos) === pos;
if(match) {
return {
type: "token",
value: token,
start: pos,
end: pos + token.length
};
}
return null;
};
/*
Look for a token matching a regex. Returns null if not found, otherwise returns {type: "regexp", match:, start:, end:,}
*/
exports.parseTokenRegExp = function(source,pos,reToken) {
var node = {
type: "regexp",
start: pos
};
reToken.lastIndex = pos;
node.match = reToken.exec(source);
if(node.match && node.match.index === pos) {
node.end = pos + node.match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a string literal. Returns null if not found, otherwise returns {type: "string", value:, start:, end:,}
*/
exports.parseStringLiteral = function(source,pos) {
var node = {
type: "string",
start: pos
};
var reString = /(?:"([^"]*)")|(?:'([^']*)')/g;
reString.lastIndex = pos;
var match = reString.exec(source);
if(match && match.index === pos) {
node.value = match[1] === undefined ? match[2] : match[1];
node.end = pos + match[0].length;
return node;
} else {
return null;
}
};
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
exports.parseMacroParameter = function(source,pos) {
var node = {
type: "macro-parameter",
start: pos
};
// Define our regexp
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for the parameter
var token = this.parseTokenRegExp(source,pos,reMacroParameter);
if(!token) {
return null;
}
pos = token.end;
// Get the parameter details
node.value = token.match[2] !== undefined ? token.match[2] : (
token.match[3] !== undefined ? token.match[3] : (
token.match[4] !== undefined ? token.match[4] : (
token.match[5] !== undefined ? token.match[5] : (
""
)
)
)
);
if(token.match[1]) {
node.name = token.match[1];
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for a macro invocation. Returns null if not found, or {type: "macrocall", name:, parameters:, start:, end:}
*/
exports.parseMacroInvocation = function(source,pos) {
var node = {
type: "macrocall",
start: pos,
params: []
};
// Define our regexps
var reMacroName = /([^\s>"'=]+)/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a double less than sign
var token = this.parseTokenString(source,pos,"<<");
if(!token) {
return null;
}
pos = token.end;
// Get the macro name
var name = this.parseTokenRegExp(source,pos,reMacroName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Process parameters
var parameter = this.parseMacroParameter(source,pos);
while(parameter) {
node.params.push(parameter);
pos = parameter.end;
// Get the next parameter
parameter = this.parseMacroParameter(source,pos);
}
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a double greater than sign
token = this.parseTokenString(source,pos,">>");
if(!token) {
return null;
}
pos = token.end;
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
exports.parseAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Get the attribute name
var name = this.parseTokenRegExp(source,pos,reAttributeName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for an equals sign
var token = this.parseTokenString(source,pos,"=");
if(token) {
pos = token.end;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = this.parseStringLiteral(source,pos);
if(stringLiteral) {
pos = stringLiteral.end;
node.type = "string";
node.value = stringLiteral.value;
} else {
// Look for an indirect value
var indirectValue = this.parseTokenRegExp(source,pos,reIndirectValue);
if(indirectValue) {
pos = indirectValue.end;
node.type = "indirect";
node.textReference = indirectValue.match[1];
} else {
// Look for a unquoted value
var unquotedValue = this.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
pos = unquotedValue.end;
node.type = "string";
node.value = unquotedValue.match[1];
} else {
// Look for a macro invocation value
var macroInvocation = this.parseMacroInvocation(source,pos);
if(macroInvocation) {
pos = macroInvocation.end;
node.type = "macro";
node.value = macroInvocation;
} else {
node.type = "string";
node.value = "true";
}
}
}
}
} else {
node.type = "string";
node.value = "true";
}
// Update the end position
node.end = pos;
return node;
};
/*
Look for an HTML tag. Returns null if not found, otherwise returns {type: "tag", name:, attributes: [], isSelfClosing:, start:, end:,}
Look for an HTML tag. Returns null if not found, otherwise returns {type: "element", name:, attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseTag = function(source,pos,options) {
options = options || {};
@@ -321,45 +84,48 @@ exports.parseTag = function(source,pos,options) {
// Define our regexps
var reTagName = /([a-zA-Z0-9\-\$]+)/g;
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a less than sign
token = this.parseTokenString(source,pos,"<");
token = $tw.utils.parseTokenString(source,pos,"<");
if(!token) {
return null;
}
pos = token.end;
// Get the tag name
token = this.parseTokenRegExp(source,pos,reTagName);
token = $tw.utils.parseTokenRegExp(source,pos,reTagName);
if(!token) {
return null;
}
node.tag = token.match[1];
if(node.tag.charAt(0) === "$") {
node.type = node.tag.substr(1);
}
pos = token.end;
// Process attributes
var attribute = this.parseAttribute(source,pos);
var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) {
node.attributes[attribute.name] = attribute;
pos = attribute.end;
// Get the next attribute
attribute = this.parseAttribute(source,pos);
attribute = $tw.utils.parseAttribute(source,pos);
}
// Skip whitespace
pos = this.skipWhiteSpace(source,pos);
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a closing slash
token = this.parseTokenString(source,pos,"/");
token = $tw.utils.parseTokenString(source,pos,"/");
if(token) {
pos = token.end;
node.isSelfClosing = true;
}
// Look for a greater than sign
token = this.parseTokenString(source,pos,">");
token = $tw.utils.parseTokenString(source,pos,">");
if(!token) {
return null;
}
pos = token.end;
// Check for a required line break
if(options.requireLineBreak) {
token = this.parseTokenRegExp(source,pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
token = $tw.utils.parseTokenRegExp(source,pos,/([^\S\n]*\r?\n(?:[^\S\n]*\r?\n|$))/g);
if(!token) {
return null;
}
@@ -379,7 +145,7 @@ exports.findNextTag = function(source,pos,options) {
// Try to parse the candidate as a tag
var tag = this.parseTag(source,match.index,options);
// Return success
if(tag && this.isLegalTag(tag.tag)) {
if(tag && this.isLegalTag(tag)) {
return tag;
}
// Look for the next match
@@ -391,11 +157,11 @@ exports.findNextTag = function(source,pos,options) {
};
exports.isLegalTag = function(tag) {
// If it starts with a $ then we'll let anything go
if(tag.charAt(0) === "$") {
// Widgets are always OK
if(tag.type !== "element") {
return true;
// If it starts with a dash then it's not legal
} else if(tag.charAt(0) === "-") {
// If it's an HTML tag that starts with a dash then it's not legal
} else if(tag.tag.charAt(0) === "-") {
return false;
} else {
// Otherwise it's OK

View File

@@ -0,0 +1,133 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/image.js
type: application/javascript
module-type: wikirule
Wiki text inline rule for embedding images. For example:
```
[img[http://tiddlywiki.com/fractalveg.jpg]]
[img width=23 height=24 [http://tiddlywiki.com/fractalveg.jpg]]
[img width={{!!width}} height={{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]
[img[Description of image|http://tiddlywiki.com/fractalveg.jpg]]
[img[TiddlerTitle]]
[img[Description of image|TiddlerTitle]]
```
Generates the `<$image>` widget.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "image";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
};
exports.findNextMatch = function(startPos) {
// Find the next tag
this.nextImage = this.findNextImage(this.parser.source,startPos);
return this.nextImage ? this.nextImage.start : undefined;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.nextImage.end;
var node = {
type: "image",
attributes: this.nextImage.attributes
};
return [node];
};
/*
Find the next image from the current position
*/
exports.findNextImage = function(source,pos) {
// A regexp for finding candidate HTML tags
var reLookahead = /(\[img)/g;
// Find the next candidate
reLookahead.lastIndex = pos;
var match = reLookahead.exec(source);
while(match) {
// Try to parse the candidate as a tag
var tag = this.parseImage(source,match.index);
// Return success
if(tag) {
return tag;
}
// Look for the next match
reLookahead.lastIndex = match.index + 1;
match = reLookahead.exec(source);
}
// Failed
return null;
};
/*
Look for an image at the specified position. Returns null if not found, otherwise returns {type: "image", attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseImage = function(source,pos) {
var token,
node = {
type: "image",
start: pos,
attributes: {}
};
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the `[img`
token = $tw.utils.parseTokenString(source,pos,"[img");
if(!token) {
return null;
}
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Process attributes
if(source.charAt(pos) !== "[") {
var attribute = $tw.utils.parseAttribute(source,pos);
while(attribute) {
node.attributes[attribute.name] = attribute;
pos = attribute.end;
pos = $tw.utils.skipWhiteSpace(source,pos);
if(source.charAt(pos) !== "[") {
// Get the next attribute
attribute = $tw.utils.parseAttribute(source,pos);
} else {
attribute = null;
}
}
}
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the `[` after the attributes
token = $tw.utils.parseTokenString(source,pos,"[");
if(!token) {
return null;
}
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the source up to the terminating `]]`
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g);
if(!token) {
return null;
}
pos = token.end;
if(token.match[1]) {
node.attributes.tooltip = {type: "string", value: token.match[1].trim()};
}
node.attributes.source = {type: "string", value: (token.match[2] || "").trim()};
// Update the end position
node.end = pos;
return node;
};
})();

View File

@@ -35,12 +35,12 @@ exports.parse = function() {
// Move past the macro call
this.parser.pos = this.matchRegExp.lastIndex;
var params = [],
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
paramMatch = reParam.exec(paramString);
while(paramMatch) {
// Process this parameter
var paramInfo = {
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6]
};
if(paramMatch[1]) {
paramInfo.name = paramMatch[1];

View File

@@ -35,12 +35,12 @@ exports.parse = function() {
// Move past the macro call
this.parser.pos = this.matchRegExp.lastIndex;
var params = [],
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
paramMatch = reParam.exec(paramString);
while(paramMatch) {
// Process this parameter
var paramInfo = {
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]|| paramMatch[6]
};
if(paramMatch[1]) {
paramInfo.name = paramMatch[1];

View File

@@ -40,12 +40,12 @@ exports.parse = function() {
var paramString = this.match[2],
params = [];
if(paramString !== "") {
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))?/mg,
var reParam = /\s*([A-Za-z0-9\-_]+)(?:\s*:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))?/mg,
paramMatch = reParam.exec(paramString);
while(paramMatch) {
// Save the parameter details
var paramInfo = {name: paramMatch[1]},
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5];
defaultValue = paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5] || paramMatch[6];
if(defaultValue) {
paramInfo["default"] = defaultValue;
}

View File

@@ -0,0 +1,114 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/prettyextlink.js
type: application/javascript
module-type: wikirule
Wiki text inline rule for external links. For example:
```
[ext[http://tiddlywiki.com/fractalveg.jpg]]
[ext[Tooltip|http://tiddlywiki.com/fractalveg.jpg]]
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "prettyextlink";
exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
};
exports.findNextMatch = function(startPos) {
// Find the next tag
this.nextLink = this.findNextLink(this.parser.source,startPos);
return this.nextLink ? this.nextLink.start : undefined;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.nextLink.end;
return [this.nextLink];
};
/*
Find the next link from the current position
*/
exports.findNextLink = function(source,pos) {
// A regexp for finding candidate links
var reLookahead = /(\[ext\[)/g;
// Find the next candidate
reLookahead.lastIndex = pos;
var match = reLookahead.exec(source);
while(match) {
// Try to parse the candidate as a link
var link = this.parseLink(source,match.index);
// Return success
if(link) {
return link;
}
// Look for the next match
reLookahead.lastIndex = match.index + 1;
match = reLookahead.exec(source);
}
// Failed
return null;
};
/*
Look for an link at the specified position. Returns null if not found, otherwise returns {type: "element", tag: "a", attributes: [], isSelfClosing:, start:, end:,}
*/
exports.parseLink = function(source,pos) {
var token,
textNode = {
type: "text"
},
node = {
type: "element",
tag: "a",
start: pos,
attributes: {
"class": {type: "string", value: "tw-tiddlylink-external"},
},
children: [textNode]
};
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the `[ext[`
token = $tw.utils.parseTokenString(source,pos,"[ext[");
if(!token) {
return null;
}
pos = token.end;
// Look ahead for the terminating `]]`
var closePos = source.indexOf("]]",pos);
if(closePos === -1) {
return null;
}
// Look for a `|` separating the tooltip
var splitPos = source.indexOf("|",pos);
if(splitPos === -1 || splitPos > closePos) {
splitPos = null;
}
// Pull out the tooltip and URL
var tooltip, URL;
if(splitPos) {
URL = source.substring(splitPos + 1,closePos).trim();
textNode.text = source.substring(pos,splitPos).trim();
} else {
URL = source.substring(pos,closePos).trim();
textNode.text = URL;
}
node.attributes.href = {type: "string", value: URL};
node.attributes.target = {type: "string", value: "_blank"};
// Update the end position
node.end = closePos + 2;
return node;
};
})();

View File

@@ -53,8 +53,7 @@ exports.parse = function() {
}];
} else {
return [{
type: "element",
tag: "$link",
type: "link",
attributes: {
to: {type: "string", value: link}
},

View File

@@ -36,8 +36,7 @@ exports.parse = function() {
textRef = $tw.utils.trim(this.match[1]);
// Prepare the transclude widget
var transcludeNode = {
type: "element",
tag: "$transclude",
type: "transclude",
attributes: {},
isBlock: true
};
@@ -48,8 +47,7 @@ exports.parse = function() {
targetField = tr.field,
targetIndex = tr.index,
tiddlerNode = {
type: "element",
tag: "$tiddler",
type: "tiddler",
attributes: {
tiddler: {type: "string", value: targetTitle}
},

View File

@@ -34,8 +34,7 @@ exports.parse = function() {
textRef = $tw.utils.trim(this.match[1]);
// Prepare the transclude widget
var transcludeNode = {
type: "element",
tag: "$transclude",
type: "transclude",
attributes: {}
};
// Prepare the tiddler widget
@@ -45,8 +44,7 @@ exports.parse = function() {
targetField = tr.field,
targetIndex = tr.index,
tiddlerNode = {
type: "element",
tag: "$tiddler",
type: "tiddler",
attributes: {
tiddler: {type: "string", value: targetTitle}
},

View File

@@ -64,8 +64,7 @@ exports.parse = function() {
}
}
return [{
type: "element",
tag: "$link",
type: "link",
attributes: {
to: {type: "string", value: linkText}
},

View File

@@ -17,7 +17,7 @@ var AndTidWiki = function(wiki) {
AndTidWiki.prototype.save = function(text,method,callback) {
// Get the pathname of this document
var pathname = decodeURIComponent(document.location.toString());
var pathname = decodeURIComponent(document.location.toString().split("#")[0]);
// Strip the file://
if(pathname.indexOf("file://") === 0) {
pathname = pathname.substr(7);

View File

@@ -19,16 +19,31 @@ TiddlyFoxSaver.prototype.save = function(text,method,callback) {
var messageBox = document.getElementById("tiddlyfox-message-box");
if(messageBox) {
// Get the pathname of this document
var pathname = document.location.pathname;
// Test for a Windows path of the form /x:/blah/blah
if(/^\/[A-Z]\:\//i.test(pathname)) {
// Remove the leading slash
pathname = pathname.substr(1);
// Convert slashes to backslashes
pathname = pathname.replace(/\//g,"\\");
var pathname = document.location.toString().split("#")[0];
// Replace file://localhost/ with file:///
if(pathname.indexOf("file://localhost/") == 0) {
pathname = "file://" + pathname.substr(16);
}
// Windows path file:///x:/blah/blah --> x:\blah\blah
if(/^file\:\/\/\/[A-Z]\:\//i.test(pathname)) {
// Remove the leading slash and convert slashes to backslashes
pathname = pathname.substr(8).replace(/\//g,"\\");
// Firefox Windows network path file://///server/share/blah/blah --> //server/share/blah/blah
} else if(pathname.indexOf("file://///") === 0) {
pathname = "\\\\" + unescape(pathname.substr(10)).replace(/\//g,"\\");
// Mac/Unix local path file:///path/path --> /path/path
} else if(pathname.indexOf("file:///") == 0) {
pathname = unescape(pathname.substr(7));
// Mac/Unix local path file:/path/path --> /path/path
} else if(pathname.indexOf("file:/") == 0) {
pathname = unescape(pathname.substr(5));
// Otherwise Windows networth path file://server/share/path/path --> \\server\share\path\path
} else {
pathname = "\\\\" + unescape(pathname.substr(7)).replace(new RegExp("/","g"),"\\");
}
// Create the message element and put it in the message box
var message = document.createElement("div");
console.log("Pathname",pathname);
message.setAttribute("data-tiddlyfox-path",decodeURIComponent(pathname));
message.setAttribute("data-tiddlyfox-content",text);
messageBox.appendChild(message);

View File

@@ -12,38 +12,22 @@ This is the main application logic for both the client and server
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "startup";
exports.after = ["load-modules"];
exports.synchronous = true;
// Set to `true` to enable performance instrumentation
var PERFORMANCE_INSTRUMENTATION = false;
// Time (in ms) that we defer refreshing changes to draft tiddlers
var DRAFT_TIDDLER_TIMEOUT = 400;
var widget = require("$:/core/modules/widgets/widget.js");
exports.startup = function() {
var modules,n,m,f,commander;
// Load modules
$tw.modules.applyMethods("utils",$tw.utils);
if($tw.node) {
$tw.modules.applyMethods("utils-node",$tw.utils);
}
$tw.modules.applyMethods("global",$tw);
$tw.modules.applyMethods("config",$tw.config);
var modules,n,m,f;
if($tw.browser) {
$tw.utils.getBrowserInfo($tw.browser);
$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));
}
$tw.version = $tw.utils.extractVersionInfo();
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
// Set up the performance framework
$tw.perf = new $tw.Performance(PERFORMANCE_INSTRUMENTATION);
// Set up the parsers
$tw.wiki.initParsers();
// Set up the command modules
$tw.Commander.initCommands();
// Kick off the language manager and switcher
$tw.language = new $tw.Language();
$tw.languageSwitcher = new $tw.PluginSwitcher({
@@ -64,24 +48,8 @@ exports.startup = function() {
"$:/themes/tiddlywiki/vanilla"
]
});
// Display the default tiddlers
var displayDefaultTiddlers = function() {
// Get the default tiddlers
var defaultTiddlersTitle = "$:/DefaultTiddlers",
defaultTiddlersTiddler = $tw.wiki.getTiddler(defaultTiddlersTitle),
defaultTiddlers = [];
if(defaultTiddlersTiddler) {
defaultTiddlers = $tw.wiki.filterTiddlers(defaultTiddlersTiddler.fields.text);
}
// Initialise the story
var storyTitle = "$:/StoryList",
story = [];
for(var t=0; t<defaultTiddlers.length; t++) {
story[t] = defaultTiddlers[t];
}
$tw.wiki.addTiddler({title: storyTitle, text: "", list: story},$tw.wiki.getModificationFields());
};
displayDefaultTiddlers();
// Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup
$tw.wiki.clearTiddlerEventQueue();
// Set up the syncer object
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki});
// Host-specific startup
@@ -101,196 +69,7 @@ exports.startup = function() {
});
// Install the animator
$tw.anim = new $tw.utils.Animator();
// 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
});
// Install the modal message mechanism
$tw.modal = new $tw.utils.Modal($tw.wiki);
$tw.rootWidget.addEventListener("tw-modal",function(event) {
$tw.modal.display(event.param);
});
// Install the notification mechanism
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
$tw.rootWidget.addEventListener("tw-notify",function(event) {
$tw.notifier.display(event.param);
});
// Install the scroller
$tw.pageScroller = new $tw.utils.PageScroller();
$tw.rootWidget.addEventListener("tw-scroll",function(event) {
$tw.pageScroller.handleEvent(event);
});
// Listen for the tw-home message
$tw.rootWidget.addEventListener("tw-home",function(event) {
displayDefaultTiddlers();
});
// Install the save action handlers
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
$tw.syncer.saveWiki({
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) {
$tw.syncer.saveWiki({
method: "autosave",
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
$tw.syncer.saveWiki({
method: "download",
template: event.param,
downloadType: "text/plain"
});
});
// Listen out for login/logout/refresh events in the browser
$tw.rootWidget.addEventListener("tw-login",function() {
$tw.syncer.handleLoginEvent();
});
$tw.rootWidget.addEventListener("tw-logout",function() {
$tw.syncer.handleLogoutEvent();
});
$tw.rootWidget.addEventListener("tw-server-refresh",function() {
$tw.syncer.handleRefreshEvent();
});
// 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) {
if(data) {
$tw.crypto.setPassword(data.password);
}
return true; // Get rid of the password prompt
}
});
});
$tw.rootWidget.addEventListener("tw-clear-password",function(event) {
$tw.crypto.setPassword(null);
});
// Ensure that $:/isEncrypted is maintained properly
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,"$:/isEncrypted")) {
$tw.crypto.updateCryptoStateTiddler();
}
});
// 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",$tw.perf.report("styleRefresh",function(changes) {
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
}
}));
// Display the $:/PageMacros tiddler to kick off the display
renderPage();
// 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",{
param: "$:/language/Modals/SaveInstructions"
});
}
// Call browser startup modules
$tw.modules.forEachModuleOfType("browser-startup",function(title,module) {
if(module.startup) {
module.startup();
}
});
} else {
// On the server, start a commander with the command line arguments
commander = new $tw.Commander(
$tw.boot.argv,
function(err) {
if(err) {
console.log("Error: " + err);
}
},
$tw.wiki,
{output: process.stdout, error: process.stderr}
);
commander.execute();
}
};
/*
Main render function for PageMacros, which includes the PageTemplate
*/
function renderPage() {
// Parse and render the template
var templateTitle = "$:/core/ui/PageMacros",
parser = $tw.wiki.parseTiddler(templateTitle);
$tw.perf.report("mainRender",function() {
$tw.pageWidgetNode = $tw.wiki.makeWidget(parser,{document: document, parentWidget: $tw.rootWidget});
$tw.pageContainer = document.createElement("div");
$tw.utils.addClass($tw.pageContainer,"tw-page-container-wrapper");
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
$tw.pageWidgetNode.render($tw.pageContainer,null);
})();
// Prepare refresh mechanism
var deferredChanges = Object.create(null),
timerId;
function refresh() {
// Process the refresh
$tw.pageWidgetNode.refresh(deferredChanges,$tw.pageContainer,null);
deferredChanges = Object.create(null);
}
// Add the change event handler
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
// Check if only drafts have changed
var onlyDraftsHaveChanged = true;
for(var title in changes) {
var tiddler = $tw.wiki.getTiddler(title);
if(!tiddler || !tiddler.hasField("draft.of")) {
onlyDraftsHaveChanged = false;
}
}
// Defer the change if only drafts have changed
if(timerId) {
clearTimeout(timerId);
}
timerId = null;
if(onlyDraftsHaveChanged) {
timerId = setTimeout(refresh,DRAFT_TIDDLER_TIMEOUT);
$tw.utils.extend(deferredChanges,changes);
} else {
$tw.utils.extend(deferredChanges,changes);
refresh();
}
}));
}
})();

View File

@@ -0,0 +1,37 @@
/*\
title: $:/core/modules/startup/commands.js
type: application/javascript
module-type: startup
Command processing
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "commands";
exports.platforms = ["node"];
exports.after = ["story"];
exports.synchronous = false;
exports.startup = function(callback) {
// On the server, start a commander with the command line arguments
var commander = new $tw.Commander(
$tw.boot.argv,
function(err) {
if(err) {
console.log("Error: " + err);
}
callback();
},
$tw.wiki,
{output: process.stdout, error: process.stderr}
);
commander.execute();
};
})();

View File

@@ -0,0 +1,43 @@
/*\
title: $:/core/modules/startup/favicon.js
type: application/javascript
module-type: startup
Favicon handling
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "favicon";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
// Favicon tiddler
var FAVICON_TITLE = "$:/favicon.ico";
exports.startup = function() {
// Set up the favicon
setFavicon();
// Reset the favicon when the tiddler changes
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,FAVICON_TITLE)) {
setFavicon();
}
});
};
function setFavicon() {
var tiddler = $tw.wiki.getTiddler(FAVICON_TITLE);
if(tiddler) {
var faviconLink = document.getElementById("faviconLink");
faviconLink.setAttribute("href","data:" + tiddler.fields.type + ";base64," + tiddler.fields.text);
}
};
})();

View File

@@ -0,0 +1,36 @@
/*\
title: $:/core/modules/startup/load-modules.js
type: application/javascript
module-type: startup
Load core modules
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "load-modules";
exports.synchronous = true;
exports.startup = function() {
// Load modules
$tw.modules.applyMethods("utils",$tw.utils);
if($tw.node && !$tw.browser) {
$tw.modules.applyMethods("utils-node",$tw.utils);
}
$tw.modules.applyMethods("global",$tw);
$tw.modules.applyMethods("config",$tw.config);
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
$tw.wiki.initParsers();
$tw.Commander.initCommands();
};
})();

View File

@@ -0,0 +1,47 @@
/*\
title: $:/core/modules/startup/password.js
type: application/javascript
module-type: startup
Password handling
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "password";
exports.platforms = ["browser"];
exports.after = ["rootwidget"];
exports.synchronous = true;
exports.startup = function() {
$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) {
if(data) {
$tw.crypto.setPassword(data.password);
}
return true; // Get rid of the password prompt
}
});
});
$tw.rootWidget.addEventListener("tw-clear-password",function(event) {
$tw.crypto.setPassword(null);
});
// Ensure that $:/isEncrypted is maintained properly
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,"$:/isEncrypted")) {
$tw.crypto.updateCryptoStateTiddler();
}
});
};
})();

View File

@@ -0,0 +1,96 @@
/*\
title: $:/core/modules/startup/render.js
type: application/javascript
module-type: startup
Title, stylesheet and page rendering
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "render";
exports.platforms = ["browser"];
exports.after = ["story"];
exports.synchronous = true;
// Default story and history lists
var PAGE_TITLE_TITLE = "$:/core/wiki/title"
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageTemplate";
// Time (in ms) that we defer refreshing changes to draft tiddlers
var DRAFT_TIDDLER_TIMEOUT = 400;
exports.startup = function() {
// Set up the title
$tw.titleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TITLE_TITLE,{document: $tw.fakeDocument, parseAsInline: true});
$tw.titleContainer = $tw.fakeDocument.createElement("div");
$tw.titleWidgetNode.render($tw.titleContainer,null);
document.title = $tw.titleContainer.textContent;
$tw.wiki.addEventListener("change",function(changes) {
if($tw.titleWidgetNode.refresh(changes,$tw.titleContainer,null)) {
document.title = $tw.titleContainer.textContent;
}
});
// Set up the styles
$tw.styleWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_STYLESHEET_TITLE,{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",$tw.perf.report("styleRefresh",function(changes) {
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
}
}));
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
$tw.perf.report("mainRender",function() {
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});
$tw.pageContainer = document.createElement("div");
$tw.utils.addClass($tw.pageContainer,"tw-page-container-wrapper");
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
$tw.pageWidgetNode.render($tw.pageContainer,null);
})();
// Prepare refresh mechanism
var deferredChanges = Object.create(null),
timerId;
function refresh() {
// Process the refresh
$tw.pageWidgetNode.refresh(deferredChanges,$tw.pageContainer,null);
deferredChanges = Object.create(null);
}
// Add the change event handler
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
// Check if only drafts have changed
var onlyDraftsHaveChanged = true;
for(var title in changes) {
var tiddler = $tw.wiki.getTiddler(title);
if(!tiddler || !tiddler.hasField("draft.of")) {
onlyDraftsHaveChanged = false;
}
}
// Defer the change if only drafts have changed
if(timerId) {
clearTimeout(timerId);
}
timerId = null;
if(onlyDraftsHaveChanged) {
timerId = setTimeout(refresh,DRAFT_TIDDLER_TIMEOUT);
$tw.utils.extend(deferredChanges,changes);
} else {
$tw.utils.extend(deferredChanges,changes);
refresh();
}
}));
// Fix up the link between the root widget and the page container
$tw.rootWidget.domNodes = [$tw.pageContainer];
$tw.rootWidget.children = [$tw.pageWidgetNode];
};
})();

View File

@@ -0,0 +1,78 @@
/*\
title: $:/core/modules/startup/rootwidget.js
type: application/javascript
module-type: startup
Setup the root widget and the core root widget handlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "rootwidget";
exports.platforms = ["browser"];
exports.after = ["load-modules"];
exports.before = ["story"];
exports.synchronous = true;
var widget = require("$:/core/modules/widgets/widget.js");
exports.startup = function() {
// 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
});
// Install the modal message mechanism
$tw.modal = new $tw.utils.Modal($tw.wiki);
$tw.rootWidget.addEventListener("tw-modal",function(event) {
$tw.modal.display(event.param);
});
// Install the notification mechanism
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
$tw.rootWidget.addEventListener("tw-notify",function(event) {
$tw.notifier.display(event.param);
});
// Install the scroller
$tw.pageScroller = new $tw.utils.PageScroller();
$tw.rootWidget.addEventListener("tw-scroll",function(event) {
$tw.pageScroller.handleEvent(event);
});
// Install the save action handlers
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
$tw.syncer.saveWiki({
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) {
$tw.syncer.saveWiki({
method: "autosave",
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
$tw.syncer.saveWiki({
method: "download",
template: event.param,
downloadType: "text/plain"
});
});
// If we're being viewed on a data: URI then give instructions for how to save
if(document.location.protocol === "data:") {
$tw.rootWidget.dispatchEvent({
type: "tw-modal",
param: "$:/language/Modals/SaveInstructions"
});
}
};
})();

View File

@@ -0,0 +1,144 @@
/*\
title: $:/core/modules/startup/story.js
type: application/javascript
module-type: startup
Load core modules
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "story";
exports.after = ["startup"];
exports.synchronous = true;
// Default story and history lists
var DEFAULT_STORY_TITLE = "$:/StoryList";
var DEFAULT_HISTORY_TITLE = "$:/HistoryList";
// Default tiddlers
var DEFAULT_TIDDLERS_TITLE = "$:/DefaultTiddlers";
// Config
var CONFIG_UPDATE_ADDRESS_BAR = "$:/config/Navigation/UpdateAddressBar"; // Can be "no", "permalink", "permaview"
var CONFIG_UPDATE_HISTORY = "$:/config/Navigation/UpdateHistory"; // Can be "yes" or "no"
exports.startup = function() {
// Open startup tiddlers
openStartupTiddlers();
if($tw.browser) {
// Set up location hash update
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,DEFAULT_STORY_TITLE) || $tw.utils.hop(changes,DEFAULT_HISTORY_TITLE)) {
updateLocationHash();
}
});
// Listen for changes to the browser location hash
window.addEventListener("hashchange",function() {
var hash = $tw.utils.getLocationHash();
if(hash !== $tw.locationHash) {
$tw.locationHash = hash;
openStartupTiddlers({defaultToCurrentStory: true});
}
},false)
// Listen for the tw-home message
$tw.rootWidget.addEventListener("tw-home",function(event) {
var storyFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE),
storyList = $tw.wiki.filterTiddlers(storyFilter);
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
});
}
};
/*
Process the location hash to open the specified tiddlers. Options:
defaultToCurrentStory: If true, the current story is retained as the default, instead of opening the default tiddlers
*/
function openStartupTiddlers(options) {
options = options || {};
// Work out the target tiddler and the story filter. "null" means "unspecified"
var target = null,
storyFilter = null;
if($tw.locationHash.length > 1) {
var hash = $tw.locationHash.substr(1),
split = hash.indexOf(":");
if(split === -1) {
target = decodeURIComponent(hash.trim());
} else {
target = decodeURIComponent(hash.substr(0,split).trim());
storyFilter = decodeURIComponent(hash.substr(split + 1).trim());
}
}
// If the story wasn't specified use the current tiddlers or a blank story
if(storyFilter === null) {
if(options.defaultToCurrentStory) {
var currStoryList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE);
storyFilter = $tw.utils.stringifyList(currStoryList);
} else {
if(target && target !== "") {
storyFilter = "";
} else {
storyFilter = $tw.wiki.getTiddlerText(DEFAULT_TIDDLERS_TITLE);
}
}
}
// Process the story filter to get the story list
var storyList = $tw.wiki.filterTiddlers(storyFilter);
// If the target tiddler isn't included then splice it in at the top
if(target && storyList.indexOf(target) === -1) {
storyList.unshift(target);
}
// Save the story list
$tw.wiki.addTiddler({title: DEFAULT_STORY_TITLE, text: "", list: storyList},$tw.wiki.getModificationFields());
// If a target tiddler was specified add it to the history stack
if(target && target !== "") {
// The target tiddler doesn't need double square brackets, but we'll silently remove them if they're present
if(target.indexOf("[[") === 0 && target.substr(-2) === "]]") {
target = target.substr(2,target.length - 4);
}
$tw.wiki.addToHistory(target);
} else if(storyList.length > 0) {
$tw.wiki.addToHistory(storyList[0]);
}
}
function updateLocationHash() {
var updateAddressBar = $tw.wiki.getTiddlerText(CONFIG_UPDATE_ADDRESS_BAR,"permaview").trim();
if(updateAddressBar !== "no") {
// Get the story and the history stack
var storyList = $tw.wiki.getTiddlerList(DEFAULT_STORY_TITLE),
historyList = $tw.wiki.getTiddlerData(DEFAULT_HISTORY_TITLE,[]);
var targetTiddler = "";
// The target tiddler is the one at the top of the stack
if(historyList.length > 0) {
targetTiddler = historyList[historyList.length-1].title;
}
// Blank the target tiddler if it isn't present in the story
if(storyList.indexOf(targetTiddler) === -1) {
targetTiddler = "";
}
// Assemble the location hash
if(updateAddressBar === "permalink") {
$tw.locationHash = "#" + encodeURIComponent(targetTiddler)
} else {
$tw.locationHash = "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList));
}
// Only change the location hash if we must, thus avoiding unnecessary onhashchange events
if($tw.utils.getLocationHash() !== $tw.locationHash) {
if($tw.wiki.getTiddlerText(CONFIG_UPDATE_HISTORY,"no").trim() === "yes") {
// Assign the location hash so that history is updated
window.location.hash = $tw.locationHash;
} else {
// We use replace so that browser history isn't affected
window.location.replace(window.location.toString().split("#")[0] + $tw.locationHash);
}
}
}
}
})();

View File

@@ -0,0 +1,34 @@
/*\
title: $:/core/modules/startup/syncer-browser.js
type: application/javascript
module-type: startup
Startup handling
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "syncer-browser";
exports.platforms = ["browser"];
exports.after = ["rootwidget"];
exports.synchronous = true;
exports.startup = function() {
// Listen out for login/logout/refresh events in the browser
$tw.rootWidget.addEventListener("tw-login",function() {
$tw.syncer.handleLoginEvent();
});
$tw.rootWidget.addEventListener("tw-logout",function() {
$tw.syncer.handleLogoutEvent();
});
$tw.rootWidget.addEventListener("tw-server-refresh",function() {
$tw.syncer.handleRefreshEvent();
});
};
})();

View File

@@ -15,10 +15,16 @@ Zooms between individual tiddlers
var ZoominListView = function(listWidget) {
var self = this;
this.listWidget = listWidget;
// Make all the tiddlers position absolute, and hide all but the first one
// Get the index of the tiddler that is at the top of the history
var history = this.listWidget.wiki.getTiddlerData(this.listWidget.historyTitle,[]),
targetTiddler;
if(history.length > 0) {
targetTiddler = history[history.length-1].title;
}
// Make all the tiddlers position absolute, and hide all but the top (or first) one
$tw.utils.each(this.listWidget.children,function(itemWidget,index) {
var domNode = itemWidget.findFirstDomNode();
if(index) {
if(targetTiddler !== itemWidget.parseTreeNode.itemTitle || (!targetTiddler && index)) {
domNode.style.display = "none";
} else {
self.currentTiddlerDomNode = domNode;

View File

@@ -18,7 +18,11 @@ exports.hasTag = function(tag) {
exports.isPlugin = function() {
return this.fields.type === "application/json" && this.hasField("plugin-type");
}
};
exports.isDraft = function() {
return this.hasField("draft.of");
};
exports.getFieldString = function(field) {
var value = this.fields[field];
@@ -53,4 +57,52 @@ exports.getFieldStringBlock = function(options) {
return fields.join("\n");
};
/*
Compare two tiddlers for equality
tiddler: the tiddler to compare
excludeFields: array of field names to exclude from the comparison
*/
exports.isEqual = function(tiddler,excludeFields) {
excludeFields = excludeFields || [];
var self = this,
differences = []; // Fields that have differences
// Add to the differences array
function addDifference(fieldName) {
// Check for this field being excluded
if(excludeFields.indexOf(fieldName) === -1) {
// Save the field as a difference
$tw.utils.pushTop(differences,fieldName);
}
}
// Returns true if the two values of this field are equal
function isFieldValueEqual(fieldName) {
var valueA = self.fields[fieldName],
valueB = tiddler.fields[fieldName];
// Check for identical string values
if(typeof(valueA) === "string" && typeof(valueB) === "string" && valueA === valueB) {
return true;
}
// Check for identical array values
if($tw.utils.isArray(valueA) && $tw.utils.isArray(valueB) && $tw.utils.isArrayEqual(valueA,valueB)) {
return true;
}
// Otherwise the fields must be different
return false;
}
// Compare our fields
for(var fieldName in this.fields) {
if(!isFieldValueEqual(fieldName)) {
addDifference(fieldName);
}
}
// There's a difference for every field in the other tiddler that we don't have
for(fieldName in tiddler.fields) {
if(!(fieldName in this.fields)) {
addDifference(fieldName);
}
}
// Return whether there were any differences
return differences.length === 0;
};
})();

View File

@@ -130,9 +130,4 @@ exports.convertEventName = function(eventName) {
return newEventName;
};
// Setup constants for the current browser
exports.getBrowserInfo = function(info) {
info.isIE = (/msie|trident/i.test(navigator.userAgent));
};
})();

View File

@@ -157,17 +157,5 @@ exports.addEventListeners = function(domNode,events) {
});
};
/*
Construct and dispatch a custom event
*/
exports.dispatchCustomEvent = function(target,name,members) {
var event = document.createEvent("Event");
event.initEvent(name,true,true);
$tw.utils.each(members,function(member,name) {
event[name] = member;
});
target.dispatchEvent(event);
};
})();

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