1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-28 05:41:26 +00:00

Compare commits

..

274 Commits

Author SHA1 Message Date
jeremy@jermolene.com
bbdf9bae89 Merge branch 'master' into publishing-framework 2021-07-14 15:48:54 +01:00
jeremy@jermolene.com
0924ca6365 Update docs that mention store area 2021-07-14 13:08:19 +01:00
jeremy@jermolene.com
39fec2decf Update release note 2021-07-14 10:12:50 +01:00
jeremy@jermolene.com
dbfd45814d Search and replace "v5.1.24" to "v5.2.0"
As discussed in #5708
2021-07-14 09:21:37 +01:00
Jeremy Ruston
d455072f13 Add support for JSON-formatted tiddler store, and make it the default (#5708)
* Add support for JSON-formatted tiddler store, and make it the default

The change to `getTiddlersAsJson()` is to allow experimentation

* Move JSON tiddlers into their own store area, and fix support for encrypted tiddlers

Also add a dummy old-style store area for backwards compatibility

The current arrangement is that JSON tiddlers will always override old-style tiddlers.

* Use the deserialiser mechanism to decode the content

* Refactor $:/core/modules/deserializers.js before we start extending it

Cleaning up the helper function names and ordering

* Drop support for the "systemArea" div

It was only used in really old v5.0.x

* Update deserializer to support JSON store format and add some tests

* Life UI restrictions on characters in fieldnames

* Add another test case

* Correct mis-merge

* Remove toLowerCase() methods applied to fieldnames

* Insert line breaks in output of getTiddlersAsJson (#5786)

Rather than have the entire store on one line, insert a line break
after each tiddler.

* Refactor #5786 for backwards compatibility

* Only read .tiddlywiki-tiddler-store blocks from script tags

Prompted by @simonbaird's comment here: https://github.com/Jermolene/TiddlyWiki5/pull/5708#discussion_r648833367

* Clean up escaping of unsafe script characters

It seems that escaping `<` is sufficient

* Add docs from @saqimtiaz

Thanks @saqimtiaz

* Docs tweaks

* Remove excess whitespace

Thanks @simonbaird

* Fix templates for lazy loading

* Remove obsolete item from release note

* Clean up whitespace

* Docs for the jsontiddler widget

* Fix whitespace

Fixes #5840

* Comments

* Fix newlines in JSON store area

* Remove obsolete docs change

Co-authored-by: Simon Baird <simon.baird@gmail.com>
2021-07-14 09:15:30 +01:00
jeremy@jermolene.com
155525708b Update release note 2021-07-13 17:50:01 +01:00
jeremy@jermolene.com
fdca11dec3 Remove unneeded table class
I think this is a typo @pmario?
2021-07-13 17:49:52 +01:00
jeremy@jermolene.com
f83875331d Update release note 2021-07-12 19:36:36 +01:00
Saq Imtiaz
be6deb054e Update ActionCreateTiddlerWidget.tid (#5871) 2021-07-11 22:39:56 +01:00
Saq Imtiaz
b0604a9bf5 Update MessageCatcher docs to clarify usage (#5870) 2021-07-11 22:39:24 +01:00
Saq Imtiaz
30925ee7bf Update syntax for Eventcatcher (#5868)
* Update syntax for Eventcatcher to be consistent with MessageCatcher while being backwards compatible

* Update docs

* Update docs
2021-07-11 20:21:35 +01:00
Bram Chen
7204f442cd Add chinese translations for ExportTiddlyWikiCore/* (#5856)
* add ExportTiddlyWikiCore/Caption
* add ExportTiddlyWikiCore/Hint
2021-07-07 11:02:33 +01:00
cdruan
23fec9e390 Fix faulty external-js single-file wiki (#5570)
* Fix problems with building single-file wiki using external-js template

* core/templates/external-js/tiddlywiki5-external-js.html.tid,
  core/templates/external-js/save-all-external-js.tid,
  core/templates/external-js/save-offline-external-js.tid
  core/templates/external-js/load-external-js.tid:
  Fix #5343. Exclude client-server plugins in tiddler imports and to
  specify a working URL for loading tiddlywiki5.js from local disk.
  Mirror save/all and save/offline templates in the regular server
  edition.

  Fix #4717 (tiddlywiki5-external-js.html.tid)

* core/modules/saver-handler.js:
  Need the change to make single file autosave work with the external-js
  template.

* editions/server-external-js/tiddlywiki.info:
  Provide external-js related build targets.

* core/language/en-GB/Snippets/ExtJSReadme.tid:
  Temporary doc to supplement TW5.com's external-js section. Demonstrate
  that upgrade could be done on single-file wikis with an externalized
  TW core.

* core/language/en-GB/Snippets/GetTiddlyWikiJS.tid:
  Documentation. Meant to be included in every wiki and to help end
  users acquire tiddlywiki5.js.

* Pre-configure save-wiki template for end-users

* Remove the newline character at the end of the file.

* Trim "template" value in saveWiki()

* Safeguard the code from extraneous whitespaces in transcluded result.

* Rename and add versioning to downloaded tiddlywiki core JS

* Rename "tiddlywiki5.js" to "twcore-VERSION.js"

* Preload $:/config/SaveWikiButton/Template tiddler with the required
  external-js template value.

* Update external-js user documentation

* Add "download tiddlywiki core JS" menu item to the "cloud" button.

* Update build's target defintions associated with external-js template.

* Move the user doc to the tw5.com edition.

* Coding style update

* Undo template name changes

* Correct text & fill colors on some disabled buttons

* Add new "export tiddlywiki core" button under page control tools

This new button can export tiddlywiki's core JS from user's wiki as
long as the wiki is served with the regular "root" template. The
button will be ineffective, thus disabled, if the core has already been
externalized by the "external-js" template.

With this button, a full standalone html wiki can obtain the matching
core JS without TiddlyWiki on node.js. Once this is done, the html wiki
can be converted to using the "external-js" template.

* Alternate version of "save tiddlywiki core for offline use"

This version will fire up a "Save File" dialogue box when clicked,
instead of directing the user to a helper doc for further instruction.
It achieves this by using the "download" attribute of the <a> html tag.
It works on most modern desktop browsers, but older browsers (e.g. IE)
may display the file instead.

* Adjust font-weight to match other menu items

* Merge two user documentations into one

* Add user-browser-cache=yes to --listen command

* Update "export tiddlywiki core" button hint

* Simpler implementation for switching btw online/offline core URL

Shave off one template by using filtered transclusion to control
online/offline core URL.

* Update user doc

Update the user doc to clarify that build index step is not needed to
initialize a new wiki.

* Rename twcore to tiddlywikicore

* Reformat the user doc

* Rework export-tiddlywikicore button

Popup an error message instead of disabling the button when export
core cannot be performed.

* Revert "Correct text & fill colors on some disabled buttons"

This reverts commit e7dbb7e712.
2021-07-06 15:02:21 +01:00
RJ Skerry-Ryan
8d9dc0cd29 Markdown: Don't emit paragraph tags when a paragraph is "tight". (#5848)
* markdown: Don't emit paragraph tags when a paragraph is "tight".

Motivation: Since the upgrade to remarkable.js (#3876), lists are rendered as
HTML like this:

```
<ul>
  <li><p>One</p></li>
  <li><p>Two</p></li>
  <li><p>Three</p></li>
</ul>
```

The paragraph nodes insert blocks that break the visual flow of the list and are
unexpected e.g. compared to WikiText markup's rendering of a bulleted list.

Solution: remarkable.js annotates certain paragraph nodes as "tight", and in the
bulleted list case, the paragraph nodes wrapping the text of each list item are
marked tight.

remarkable uses the tight property to [elide paragraph tags in its
renderer](58b6945f20/lib/rules.js (L136-L142)).

This change implements the equivalent logic in TiddlyWiki's markdown rendering:
If a paragraph is marked tight, then we elide the `<p>` tag wrapping its children.

* Use ES5 Array.concat instead of ES6 spread operator.
2021-07-06 11:33:12 +01:00
RJ Skerry-Ryan
a1d9464011 Add optional KaTeX support to markdown plugin (#5846)
* Add optional KaTeX support to the tiddlywiki/markdown plugin.

Uses the remarkable-katex plugin 1.1.8 by Brad Howes to enable KaTeX support if
the tiddlywiki/katex plugin is installed. Fixes #2984.

TESTED:

Created a test wiki with:
```
$ node tiddlywiki.js test --init markdowndemo
$ node tiddlywiki.js test --listen
```

* Verified markdown support works without the tiddlywiki/katex plugin enabled.
* Verified markdown support works with the tiddlywiki/katex plugin enabled.
* Verified KaTeX (both inline and blocks) work as expected when the
tiddlywiki/katex plugin is enabled.

* Mention remarkable-katex plugin usage in the readme Tiddler.

* Include the remarkable-katex license as a tiddler.

* Include the Remarkable license.

* Include unminified original source of remarkable-katex 1.1.8.
2021-07-06 11:32:32 +01:00
jeremy@jermolene.com
0b71f25f74 Revert "Update sync methods (#5467)"
This reverts commit 8d7930f660.

See the discussion at https://github.com/Jermolene/TiddlyWiki5/pull/5467#issuecomment-873590578https://github.com/Jermolene/TiddlyWiki5/pull/5467#issuecomment-873590578
2021-07-05 19:26:20 +01:00
jeremy@jermolene.com
315464372f Version tags missed off 56068d8215 2021-07-05 10:09:04 +01:00
jeremy@jermolene.com
56068d8215 tm-navigate: add separate properties to access bounds of client rectangle
Makes it easier to use the client rectangle information within an action handler
2021-07-05 09:52:17 +01:00
jeremy@jermolene.com
1b55eb9eee Docs improvements; missed off 3094e06236 2021-07-02 14:41:59 +01:00
jeremy@jermolene.com
3094e06236 Add support for full refreshing of action widgets
Fixes #5791
2021-07-02 14:33:38 +01:00
jeremy@jermolene.com
f87b3bfcdb Extend messagecatcher widget to allow setting multiple handlers at once 2021-06-30 16:17:59 +01:00
jeremy@jermolene.com
a0a0df9655 Update action-navigate widget with metakeys to match link widget 2021-06-30 16:11:21 +01:00
jeremy@jermolene.com
31c1584b9a Extend $tw.utils.removeArrayEntries to return the array 2021-06-30 16:10:52 +01:00
Saq Imtiaz
f1f951e849 Docs for macro parameters in filter operands (#5837) 2021-06-29 23:25:44 +01:00
Saq Imtiaz
041c3e817c Support for macro params in filter operands (#5836)
* Exploratory pass at adding support for macro params in filter operands

* whitspace correction

* rename varInfo to varTree for disambiguation

* Refactored parseMacroInvocation to be re-usable, performance improvements for variables with no params and tests

* Revised regular expression and removed spurious white space changes

* Revised regular expression and removed spurious white space changes

* More whitespace cleanup and added more tests for edge cases

* Added test for macro params with square brackets
2021-06-29 22:21:39 +01:00
jeremy@jermolene.com
70e60cd93f Remove whitespace from plugin text
https://github.com/Jermolene/TiddlyWiki5/pull/5708#issuecomment-870749131

Has no effect on functionality, but makes the prerelease index.html go from 6821151 to 6680944 bytes (saving 6680944-6821151=-140,207 bytes or (6680944-6821151)/6680944=2.1%
2021-06-29 22:17:16 +01:00
Saq Imtiaz
a6990128f1 Fixed bug introduced into transclusions for blank fields in #5736 (#5835) 2021-06-29 12:07:14 +01:00
jeremy@jermolene.com
338b7c92a2 Ensure tiddlers with fieldnames containing colons don't get saved in .tid file format
Prompted by discussion over at https://github.com/Jermolene/TiddlyWiki5/pull/5708#issuecomment-862399985
2021-06-27 21:27:57 +01:00
Mario Pietsch
a409536ad0 Prevent scrolling of the page when modals are displayed (#5816)
* prevent scroll-chaining in modals

* make body overflow hidden to prevent background scrolling
2021-06-27 16:24:06 +01:00
Joe Bordes
c9af04d0e5 New Spanish translation strings (#5822) 2021-06-25 17:57:17 +01:00
Saq Imtiaz
076a04fbfb Added docs for th-closing-tiddler hook (#5820) 2021-06-23 09:51:46 +01:00
jeremy@jermolene.com
83ee363cb4 Add charcode operator to make it easier to generate strings containing control characters
Avoids some confusing hacks. @saqimtiaz I'm guessing you might have already done something like this?
2021-06-22 21:52:00 +01:00
Adam Sherwood
63fa0c4fa4 Hook for closing tiddlers (#3797) 2021-06-22 19:51:35 +01:00
Bram Chen
644062fc21 Add chinese translations for import cancel warning (#5818) 2021-06-22 09:58:38 +01:00
Saq Imtiaz
021e9b8c4d :map filter run prefix with docs and tests (#5813) 2021-06-21 20:59:58 +01:00
Mario Pietsch
afa653a7aa Improve import cancel warning (#5812) 2021-06-21 20:58:58 +01:00
Mario Pietsch
0b56d5fd37 update German translation (#5811) 2021-06-21 12:14:36 +01:00
jeremy@jermolene.com
2da7ae0b73 Action-createtiddler: Ensure child widgets are refreshed before invocation
Fixes #5791
2021-06-14 18:13:51 +01:00
Mario Pietsch
9c0d6a46cc Add "commentpragma" html style rule (#5726)
* html-comment, that can be used in the pragma area

* add commentpragma test

* fix typo

* fix typo and change comments ab bit

* combine html-comment and pragma-comment and add some docs, how to use it

* Make docs simpler by removing caching info

* change h2 wording
2021-06-14 17:39:56 +01:00
Saq Imtiaz
06318b7617 Pass reference to widget to CodeMirror (#5790) 2021-06-14 16:46:39 +01:00
Saq Imtiaz
8f9e8c1dee Keyboard widget: provide variable for shortcut descriptor to actions. (#5782) 2021-06-14 12:03:59 +01:00
Simon Huber
3cd80de5bb Revert #5720 and fix #5770 by removing :root { color-scheme: ... } 2021-06-14 11:01:00 +01:00
Simon Huber
f2e26927c1 Add test for event.event.target being undefined in the tm-focus-selector listener (#5771) 2021-06-14 10:59:31 +01:00
felixhayashi
960160b3a2 word break property when viewing field values (#1661) 2021-06-14 10:37:04 +01:00
Saq Imtiaz
4f33d2f35c Update release notes (#5780) 2021-06-11 18:15:07 +01:00
Odin
b5db488438 Update release notes 5.1.24 to 5.2.0 (#5754) 2021-06-11 17:56:45 +01:00
Simon Huber
6dd1887f0b Use event.event.view.confirm for confirmation messages in navigator.js and action-confirm.js (#5776) 2021-06-11 16:56:06 +01:00
Simon Huber
219beb13cc Add test to storyviews if targetElement is null (#5767)
* Update classic.js

* Update pop.js

* Update zoomin.js

* simplify test in classic.js

* simplify test in pop.js

* simplify test in zoomin.js
2021-06-09 10:18:15 +01:00
Simon Huber
c18b7527a7 Fix #5760 - tm-focus-selector doesn't work in new windows (#5766)
* Pass the original event to invokeActionString

* Update rootwidget.js
2021-06-06 12:42:28 +01:00
Simon Huber
2f1806ab6a Keyboard widget: don't refresh when class changes (#5758) 2021-06-06 11:03:08 +01:00
Simon Huber
afa4ea3d03 Make navigation in new windows work for storyviews (#5759) 2021-06-06 10:47:19 +01:00
Simon Huber
2b911ac11f Make the insert- and remove-animations of storyviews work in new windows (#5755)
* Make classic storyview work in new windows, too

* Make pop storyview work in new windows, too

* Make zoomin storyview insert and remove animation work in new windows, too
2021-06-04 16:59:45 +01:00
jeremy@jermolene.com
056e6541a1 Revert 582b156d5f: Refresh non-action widgets before invocation 2021-06-02 21:47:28 +01:00
jeremy@jermolene.com
753bf8fe62 Revert "Revert "Transclude widget: refresh selectively when needed (#5736)""
This reverts commit 4f9dd50382.
2021-06-02 21:45:06 +01:00
jeremy@jermolene.com
4f9dd50382 Revert "Transclude widget: refresh selectively when needed (#5736)"
This reverts commit 2e695801b1.
2021-06-02 19:14:05 +01:00
Saq Imtiaz
2e695801b1 Transclude widget: refresh selectively when needed (#5736)
* Transclude widget: only refresh when transcluded text reference has changed, includes tests

* Refactor wiki.parseTextReference so it is re-usable for getting the parser info

* Re-arrange methods in wiki.js to improve diff readability
2021-06-02 13:58:30 +01:00
jeremy@jermolene.com
f1d76a1eee Merge branch 'master' into publishing-framework 2021-06-01 13:17:47 +01:00
jeremy@jermolene.com
55c522ab8f Improve comments
As per @pmario's comment at 582b156d5f (commitcomment-51566608)
2021-06-01 11:49:05 +01:00
jeremy@jermolene.com
9faaa31299 Extend action-createtiddler to make new title available as a variable
I'm not sure if the docs are clear, but this is quite a big deal, and along with 582b156d5f makes working with action widgets a lot easier.
2021-06-01 09:41:14 +01:00
jeremy@jermolene.com
582b156d5f Refresh non-action widgets before invoking them
Fixes #5744
2021-06-01 09:28:04 +01:00
Bram Chen
652e8b1262 Update chinese translations (#5740) 2021-05-31 07:37:01 +01:00
Joe Bordes
82ec63e711 style(App) eliminate whitespace at the end of code lines (#5735) 2021-05-30 19:20:17 +01:00
Joe Bordes
51fd02d9b6 i18n(en-GB) apply grammarly recommendations found while translating es-ES (#5733) 2021-05-30 18:51:44 +01:00
Joe Bordes
1a6d3e686b i18n(EditorPreview) translate difference view caption (#5732) 2021-05-30 18:49:57 +01:00
Joe Bordes
e694145eec i18n(es-ES) update to version 5.1.23 (#5731) 2021-05-30 18:49:03 +01:00
Simon Huber
3a740b23bb Add tc-small-gap-right to tag-pills in tags editTemplate (#5727) 2021-05-27 14:07:50 +01:00
jeremy@jermolene.com
082aeb92ac Revert "extend lookup op flexibility with 2 parameters (#5315)"
This reverts commit 81b5fe944a.

See https://github.com/Jermolene/TiddlyWiki5/pull/5315#issuecomment-848725198 for explanation
2021-05-26 13:25:19 +01:00
Bram Chen
903cfd98a6 Update chinese translations (#5704) 2021-05-26 07:54:05 +01:00
Simon Huber
eaf1da66b6 Add color-scheme: dark/light to the root element ... (#5720) 2021-05-25 22:22:21 +01:00
Mario Pietsch
c6ed4aa84e allow us to import formerly blocked system tiddlers (#5479) 2021-05-25 22:21:57 +01:00
Mario Pietsch
123666c240 Add th-before-importing hook mechanism (#5464) 2021-05-25 22:19:58 +01:00
Mario Pietsch
68930ceb1b Extend keyboard widget (#5648) 2021-05-25 22:18:37 +01:00
Chris Nicoll
fcea51bb95 Fix typo in saqimtiaz username (#5721) 2021-05-25 21:06:30 +01:00
Joshua Fontany
8d7930f660 Update sync methods (#5467) 2021-05-24 21:16:23 +01:00
Saq Imtiaz
7a41283c6b Format:titlelist operator (#5665) 2021-05-24 19:28:43 +01:00
BlueGreenMagick
c30ce544d1 Fix ViewToolbar items inconsistent spacing (#5473) 2021-05-24 19:24:37 +01:00
Mohammad Rahmani
dcba17fc5f Correct pointer shape and color for disabled button (#5692)
* Update base.tid

this PR addresses the #5625

* Update base.tid

The extra space has been removed!
2021-05-23 18:13:04 +01:00
Mario Pietsch
2ab0474e14 Fix configuration list of HTML5 block elements (#5469) 2021-05-23 17:50:27 +01:00
Cameron Fischer
61714cbda3 Fixed super minor issue with import pragma (#5521) 2021-05-23 17:39:06 +01:00
jeremy@jermolene.com
8fbf52e419 Don't issue plugin reload warning for plugin-type: import
Fixes #5719
2021-05-23 11:19:46 +01:00
Xavier Cazin
3fe5b77770 Updates to fr-FR translations (#5718)
* fr-FR help for the use-browser-cache param of the listen command

* fr-FR dialog heading for drag&drop image import in editor

* fr-FR translations for PutForbidden & PutUnauthorized errors

* fr-FR translations for TiddlySpot and TiddlyHost saver information

* Update to fr-FR translations for named filters in $:/AdvancedSearch tab

* fr-FR translation update for the render command help

* fr-FR update to ModuleTypes translations

* fr-FR help update for the sse-enabled param of the listen command

* fr-FR update to ControlPanel Basics information

* fr-FR translation improvements to TiddlerInfo captions and hints

* fr-FR translation for the Layout Switcher caption

* fr-FR translation updates for Layout-related information

* fr-FR translation for ConfirmAction

* fr-FR for the captions related to tag input clearing
2021-05-23 11:07:55 +01:00
jeremy@jermolene.com
485779f5b2 Fix crash when accessing variables in filters that don't have a widget context
This should catch a large number of crashes, including:

Fixes #5716
2021-05-22 20:00:24 +01:00
Saq Imtiaz
3fc7895af2 CurrentTiddler variable consistency in subfilters and prefixes (#5691)
* Make currentTiddler variable consistent in subfilters and filter run prefixes

* Updated filterun prefix and subfilter operators to use ..currentTiddler instead of outerCurrentTiddler
2021-05-22 19:43:37 +01:00
Saq Imtiaz
bf25c4d34a Docs for new system tag $:/tags/EditorTools (#5705) 2021-05-22 11:07:55 +01:00
Saq Imtiaz
10b20657cc Deserializers[] filter operator (#5673) 2021-05-22 10:50:11 +01:00
Saq Imtiaz
0003d70132 New text operation insert-text (#5707) 2021-05-21 10:35:40 +01:00
Joshua Fontany
81b5fe944a extend lookup op flexibility with 2 parameters (#5315) 2021-05-21 10:11:23 +01:00
Saq Imtiaz
270ead4701 Eventcatcher: Fixed FF and IE bugs, added stopPropagation attribute (#5711) 2021-05-21 09:43:20 +01:00
Nicolas Petton
1ddc3ab037 Add throttling for changed tiddlers prefixed with $:/temp/volatile/ (#5458) 2021-05-21 08:51:15 +01:00
jeremy@jermolene.com
160c154ef1 Merge branch 'master' into publishing-framework 2021-05-20 13:53:29 +01:00
Saq Imtiaz
05d38054c8 Drag and drop images in the editor to import and insert (#5699)
* Merge

* Clean up

* More clean up

* Ensure image import works when type is not set, clean up post import actions

* Removed spurious new line

* For non image files insert a tiddler link

* Added documentation for new settings and features
2021-05-19 21:52:43 +01:00
jeremy@jermolene.com
c7f6cedc43 Update release note 2021-05-19 14:23:54 +01:00
Mario Pietsch
ec1df7edf0 Fix whitespace in themes (#5700) 2021-05-19 14:12:12 +01:00
jeremy@jermolene.com
dbd3f835bf Fix crash when sorting by non-string fields
tags, list, created, modified are not stored as strings by default.

Fixes #5701
2021-05-19 14:10:39 +01:00
Odin
fe12a4adbf Update releasenotes 5.1.24 (#5670)
* Update releasenotes 5.1.24 

This includes changes up to 06-05-2021

* Incorporated feedback into release notes 5.1.24

Incorporated feedback and moved the '[[ActionPopupWidget]] to create floating popups that must be manually cleared' under widget improvements.
2021-05-19 13:21:22 +01:00
Saq Imtiaz
b267a71f2d Dropzone: persistent dragover state fix (#5688) 2021-05-16 14:01:46 +01:00
Bram Chen
e7b3f69162 Add chinese help texts for use-browser-cache (#5677) 2021-05-10 19:27:48 +01:00
FlashSystems
f4d7b2c7f7 Network performance optimizations for node.js (#5436) 2021-05-08 16:05:39 +01:00
ualich
e699cf1fe8 Display tiddler link in 'Target tiddler already exists' warning (#5672) 2021-05-06 12:25:29 +01:00
jeremy@jermolene.com
d8ac00a108 TiddlyWebAdaptor: Avoid crashing if server sent events not available
Fixes #5663
2021-05-04 17:31:37 +01:00
Mario Pietsch
cf56a17f28 allow unusedtitle macro to use the prefix parameter and fix wiki.generateNewTitle() (#5361) 2021-05-02 19:26:50 +01:00
Saq Imtiaz
3f98686153 Extend <-popup> to create floating popups that must be manually cleared (#5655) 2021-05-02 10:20:39 +01:00
Saq Imtiaz
cb44cc0f2b Add :sort filter run prefix (#5653)
* Add :sort filter run prefix, docs and tests. Also extended .utils.makeCompareFunction with a flag for caseSensitivity.

* Documentation updates

* Move case sensitivity handling entirely to utils method so it is reusable
2021-05-01 13:58:40 +01:00
Saq Imtiaz
44df6fe52f Fixed issue with widget not being available to filter operator, added test (#5640) 2021-05-01 10:00:32 +01:00
Bram Chen
cb34c695b5 Update chinese error messages for the put saver (#5650) 2021-04-28 14:22:23 +01:00
Saq Imtiaz
07caa16e87 Extend dropzone to also use the specified deserializer for strings either dropped or pasted on to the dropzone. (#5601) 2021-04-27 10:15:27 +01:00
Simon Baird
30d23196b6 Add 401 and 403 error messages for the put saver (#5638) 2021-04-27 10:14:04 +01:00
Jeremy Ruston
bf773eb39a Add "average" filter operator for arithmetic mean (#5612) 2021-04-27 10:09:13 +01:00
jeremy@jermolene.com
4a99e0cc7d Change "index" attribute of list widget to "counter", and use 1-based counting
Extends #5611
2021-04-26 14:41:26 +01:00
Saq Imtiaz
e2379b599e Fixes Action-listops bug (#5644) 2021-04-26 11:29:16 +01:00
Saq Imtiaz
8203ee06c3 Allow suffixes for filter runs (#5252)
* Make filter run prefixes extensible

* Make filter run prefixes extensible

* Support rich suffixes for filter runs

* merged conflicts

* Pass suffixes to filterrunprefix
2021-04-25 19:37:47 +01:00
Mario Pietsch
ac15334bb0 Add support for disabled editor toolbar buttons & docs (#5294)
* add dynamic toolbar buttons + HowTo

* remove some whitespace.

* move howto and improve shortcut logic

* move howto

* add whitespace so it can be removed in an other PR.
2021-04-25 16:17:32 +01:00
Mario Pietsch
8849ed0d46 Fix refreshing of select widget when attributes change (#5635) 2021-04-25 16:05:02 +01:00
Saq Imtiaz
ca1cf7bb41 MessageCatcher docs: corrected typo (#5632) 2021-04-25 08:24:02 +01:00
Bram Chen
80133895ba Update chinese translations for Saving/TiddlySpot/ (#5633) 2021-04-25 08:22:03 +01:00
Simon Baird
5e236d35a5 Revise the TiddlySpot Saver settings form (#5628)
Mention TiddlyHost and link to some documentation on the
configuration options.

Also remove the TiddlySpot control panel and backups links since
they no longer work.

Notes:
* The last three fields are no use for TiddlySpot or TiddlyHost, but
  it's possible that someone, somewhere is still using the old
  store.php from Bidix's UploadPlugin, and would miss them if they
  were removed.

  I'd be happy to remove them in a future PR, if it's decided they
  can be retired.

  (If they were removed, I could delete the last row here:)
  https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot

* It's still called "TiddlySpot Saver" which I think is fine for
  now. TiddlyHost might use a different saving method in future
  so keeping the existing name seems best.
2021-04-24 08:54:44 +01:00
Jeremy Ruston
85ba7ac041 Extend list widget with "index" attribute (#5611)
* Extend list widget with "index" attribute

* Fix refreshing bug

* Clarify performance note
2021-04-20 09:15:11 +01:00
jeremy@jermolene.com
a725da2b39 Merge branch 'tiddlywiki-com' 2021-04-18 10:10:39 +01:00
jeremy@jermolene.com
7878e77e96 Update docs for PUT and DELETE APIs to mention CSRF requirements 2021-04-18 10:09:49 +01:00
jeremy@jermolene.com
c325380231 Run the SVG optimiser on the new plus/minus icons 2021-04-16 09:25:07 +01:00
jeremy@jermolene.com
a6a2535c3a Add plus/minus icons 2021-04-16 09:21:47 +01:00
jeremy@jermolene.com
caec6bc3fe Update SVG optimiser script 2021-04-16 09:20:39 +01:00
jeremy@jermolene.com
ac022ec79f Fix typo 2021-04-11 11:28:21 +01:00
jeremy@jermolene.com
89546b3357 Add a hidden setting to control HTML sandboxing 2021-04-11 10:10:16 +01:00
jeremy@jermolene.com
184083ad1a Use variable definition in the job/sitemap/route text instead of from var-* fields 2021-04-10 17:42:35 +01:00
jeremy@jermolene.com
9c62bd8030 Fix typo in link widget 2021-04-10 17:41:41 +01:00
jeremy@jermolene.com
55173c17a3 Remove obsolete link 2021-04-10 16:42:25 +01:00
jeremy@jermolene.com
b7419dec3a Finish refactoring of server <-> sitemap interface
Continuing c4cdb1ed8c
2021-04-10 13:51:07 +01:00
jeremy@jermolene.com
02d390a673 Add support for slugify to the link widget's tv-wikilink-template handling 2021-04-10 10:58:55 +01:00
jeremy@jermolene.com
c4cdb1ed8c Refactor sitemap route handling
To avoid duplicating the rendering code
2021-04-10 10:58:26 +01:00
jeremy@jermolene.com
5fcff1f1a3 Refactor server route handling to handle default documents properly 2021-04-10 10:57:52 +01:00
Saq Imtiaz
7f3fed2f50 Update DropzoneWidget.tid (#5598) 2021-04-10 10:23:16 +01:00
Saq Imtiaz
eced60853f Extend Dropzone widget (#5597)
* Extend dropzone widget with optional actions invoked after tm-import-tiddlers message has been sent. Allows triggering an alternative UX for the import

* Allow restricting a dropzone to specific mimeTypes via mimeTypes and mimeTypesPrefix attributes

* Use a mimeTypesFilter instead of the mimeTypes and mimeTypesPrefix attributes

* Updated refresh handling

* Syntax cleanup

* Replace references to mimeType with content type for consistency with existing documentation. Update documentation for DropZone widget
2021-04-10 09:48:50 +01:00
jeremy@jermolene.com
b9647b2c48 Ensure Fieldmangler widget doesn't propogate events that it traps
Fixes #5593
2021-04-08 16:56:36 +01:00
jeremy@jermolene.com
a8770d7645 Revert changes to image widget 2021-04-08 14:27:30 +01:00
jeremy@jermolene.com
953fb9f237 BibTeX Plugin: Force fieldnames to be lowercase
Fixes #5591
2021-04-07 17:43:41 +01:00
jeremy@jermolene.com
df2a3fdefd Refactor sitemap handling so we can reuse it in the webserver 2021-04-07 12:16:12 +01:00
jeremy@jermolene.com
b90aad9cea Fix typo in filtered permalink example
Fixes #5588
2021-04-06 13:13:12 +01:00
jeremy@jermolene.com
a8c248eb3d Revert to using parameterised paths instead of filters
Because we will be able to run parameterised paths in reverse for HTTP serving, which we can't do with filters
2021-04-06 12:19:49 +01:00
jeremy@jermolene.com
96103d5d4c Link to the PR 2021-04-05 17:09:43 +01:00
jeremy@jermolene.com
a025bce21f Clean up before publishing a snapshot to TiddlyHost 2021-04-05 17:07:19 +01:00
jeremy@jermolene.com
45cdd7bdf7 Merge branch 'master' into publishing-framework 2021-04-05 12:31:46 +01:00
jeremy@jermolene.com
e2d35751e2 Rebuild readme.md and contributing.md 2021-04-05 10:11:29 +01:00
jeremy@jermolene.com
fdf89f83c2 Fix typo in v5.1.24 release note 2021-04-05 10:11:03 +01:00
jeremy@jermolene.com
509356c696 Add Node.js support, refactor modelling of jobs and sitemaps, and use modals framework 2021-04-04 13:18:41 +01:00
jeremy@jermolene.com
dce425ecb8 Update release note
Apologies for the delay
2021-04-04 11:48:24 +01:00
jeremy@jermolene.com
55735d7552 BibTeX plugin: Report errors more sanely
Fixes #5581
2021-04-04 11:25:39 +01:00
jeremy@jermolene.com
a8fe653e3c Update contributing guidelines 2021-04-02 14:45:17 +01:00
jeremy@jermolene.com
013218b852 Further updates to contributing guidelines 2021-04-02 14:39:29 +01:00
jeremy@jermolene.com
c976aad5e0 Update the contributing guidelines
Following the discussion in #5484
2021-04-02 13:15:39 +01:00
jeremy@jermolene.com
28521d82f3 Revert "Extend transclude widget to optionally set variables"
Actually a partial reversion, because we're keeping the minor refactoring of makeChildWidget() in widget.js

This reverts commit 80ee5adb14.
2021-04-02 09:47:38 +01:00
jeremy@jermolene.com
54d3782167 Add version banner for docs for #5383 2021-04-02 09:34:27 +01:00
Cameron Fischer
ef6307a64e Do not escape double quotes in tiddler DIVs to save space (#5383)
* double quotes are no longer escaped in html bodies

* changed tiddlyweb's html-div-tiddler; documentation

French version still needs a translation though
2021-04-02 09:32:32 +01:00
cdruan
3b35411aba Change css-escape-polyfill to a tw uitility method (#5552)
* Replace css-escape-polyfill.js with escapecss.js utility module

* Add $tw.utils.escapeCSS() method and invoke that function within the
  escapecss operator.

* Add test cases for the "escapecss" filter operator

* Fix $tw.boot.doesTaskMatchPlatform() so it works as expected if
  a module's export.platforms contains more than one values

* Add missed files to the last commit
2021-04-02 09:25:01 +01:00
jeremy@jermolene.com
d6ea369f5e Edit text widgets should use default text for missing fields 2021-03-31 14:15:01 +01:00
Mario Pietsch
55e44a9554 This PR add tc-tiny-gap-xxx to the vanilla theme. It is similar to &nbsp; and should replace it. (#5574) 2021-03-29 16:45:12 +01:00
Saq Imtiaz
860568136f ViewSwitcher : use Button widget instead of LinkWidget (#5573) 2021-03-29 09:02:47 +01:00
Mario Pietsch
85835ebe42 fix 5424 add button is in new line (#5425) 2021-03-26 09:32:12 +00:00
Joshua Fontany
3d608892bd targeted fix for 5366 (#5416) 2021-03-26 08:42:31 +00:00
Joshua Fontany
5be647b610 Fix 4461 (#5522) 2021-03-26 08:41:41 +00:00
Joshua Fontany
a2e7cc51b5 Fix 5483 & 3483 (#5504) 2021-03-26 08:39:32 +00:00
FND
c3955c3cf9 Add another podcast link (#5567) 2021-03-24 21:21:45 +00:00
jeremy@jermolene.com
226df2ad7d Fix exporting of tiddlers that begin and end with double quotes 2021-03-23 09:27:16 +00:00
jeremy@jermolene.com
8d763f7682 Merge branch 'tiddlywiki-com' 2021-03-22 15:24:15 +00:00
jeremy@jermolene.com
f5887d9e25 Add a link to the community aggregator 2021-03-22 15:22:49 +00:00
jeremy@jermolene.com
7f202f35b4 Minor refactoring for clarity
See 9af68297cd (r48540814)
2021-03-22 09:50:54 +00:00
jeremy@jermolene.com
42e10d030a First commit 2021-03-22 09:34:32 +00:00
jeremy@jermolene.com
9c31ff1fb1 Use window.setTimeout(fn,0) for $tw.utils.nextTick in the browser
It seems that best practice has now moved to using zero:

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
2021-03-22 09:08:32 +00:00
twMat
0beac47243 Update SelectWidget.tid (#5556)
Placeholder value - Correction of previous attempt.
2021-03-21 16:55:18 +00:00
twMat
99bef2614c Update SelectWidget.tid (#5555)
Added instrux for placeholder value. [Ref.](https://github.com/Jermolene/TiddlyWiki5/issues/5544)
2021-03-20 22:43:35 +00:00
Bram Chen
a44a8c31f0 Update chinese help texts for render command (#5553) 2021-03-20 09:43:36 +00:00
jeremy@jermolene.com
8aad7b00ab Render command: fix bug with multiple variable usage 2021-03-19 18:35:10 +00:00
jeremy@jermolene.com
a38dc17300 Extend render command to allow multiple variables to be passed 2021-03-19 17:09:53 +00:00
jeremy@jermolene.com
9af68297cd Fix transclusion refreshing
Missed off 80ee5adb14
2021-03-19 16:14:15 +00:00
jeremy@jermolene.com
80ee5adb14 Extend transclude widget to optionally set variables
Partially fixes #5199
2021-03-19 15:37:59 +00:00
cdruan
743d9c56c0 Signing the CLA (#5551) 2021-03-18 08:57:43 +00:00
Cameron Fischer
427eb6d085 Refactored filter tests to use nifty spyOn method (#5550) 2021-03-18 08:57:21 +00:00
Mario Pietsch
715ce6b603 Add tag: Community Edditions (#5548)
Add tag: Community Edditions
2021-03-18 08:54:54 +00:00
jeremy@jermolene.com
a6958bfe85 Fix css-escape-polyfill.js on old iOS
Fixes #5546
2021-03-14 10:34:41 +00:00
jeremy@jermolene.com
7b1a0c6e6a Fix ES5 issue
Fixes #5545
2021-03-14 10:27:05 +00:00
jeremy@jermolene.com
e157d16b72 Add data-tag-title attribute to tag pills
Fixes #5543
2021-03-13 13:19:12 +00:00
Mario Pietsch
05acf3dce4 fix wiki.search options invert init problem (#5542) 2021-03-12 21:12:06 +00:00
Quentin Minster
37fd52e6c9 Signing the CLA (#5536) 2021-03-10 22:33:50 +00:00
jeremy@jermolene.com
85646e5db3 Update tw5.com docs macro to allow macros within examples
This was supposed to be committed before 9eda02868
2021-03-09 18:11:36 +00:00
jeremy@jermolene.com
9eda02868f Introduce messagecatcher widget 2021-03-09 18:07:07 +00:00
jeremy@jermolene.com
8980927b54 Build empty.html with the main edition
So that we get the OfficialPluginLibrary tiddler added in c69a3e827 included in the empty prerelease
2021-03-09 09:23:46 +00:00
jeremy@jermolene.com
c69a3e827a Include correct plugin library in prerelease edition 2021-03-08 23:01:55 +00:00
twMat
3c9ee052a3 Update SystemTags.tid (#5530)
Interestingly, in spite of the missing quote characters, the tiddler renders well on 

https://tiddlywiki.com/#SystemTags

but not on 

https://tiddlywiki.com/prerelease/#SystemTags
2021-03-08 18:00:41 +00:00
jeremy@jermolene.com
81546c5bf4 Menubar plugin: Add optional dropdown-position
Fixes #5533
2021-03-08 17:47:04 +00:00
jeremy@jermolene.com
5e4430dbf9 Fix Radio widget to refresh selectively, and use the checked attribute properly 2021-03-07 15:49:07 +00:00
jeremy@jermolene.com
93f4b5dac9 Merge branch 'tiddlywiki-com' 2021-03-07 10:33:08 +00:00
jeremy@jermolene.com
b58e4236b7 Docs tweaks
* The "tip" macro isn't designed to be used in a table cell (it generates a blockquote)
* We avoid full stops at the end of table entries or list items

It seems to be incredibly hard to police consistency with documentation but I think it's very important
2021-03-07 10:32:51 +00:00
jeremy@jermolene.com
60e40b5af9 Merge branch 'tiddlywiki-com' 2021-03-07 10:25:45 +00:00
jeremy@jermolene.com
6e93770459 Update RangeWidget and RadioWidget examples from #5158
@pmario we avoid using the details element because it doesn't remember its state across refreshes. It's not something that we should encourage people to use if they don't understand the limitations.

I also simplified the radio widget example because putting all the options on one line with a vertical bar separator is not a common way to display radio buttons.
2021-03-07 10:23:14 +00:00
jeremy@jermolene.com
d56e8764a1 Button widget: apply aria-expanded attribute when controlling a popup
Addresses (1) and (5) from #5519
2021-03-01 17:59:29 +00:00
Bram Chen
e84c87ef37 Update chinese language files (#5514)
* Add chinese descriptions for module-type `utils-browser`
* Fixed typos
2021-02-23 17:26:17 +00:00
jeremy@jermolene.com
ef76349c37 Add support for utils-browser modules 2021-02-22 12:11:39 +00:00
jeremy@jermolene.com
010fa140c7 Bug issue template: Add section about configuration 2021-02-20 10:43:01 +00:00
jeremy@jermolene.com
625ea364c4 Fix typo in Chinese (Simplified) 2021-02-17 12:49:45 +00:00
morosanuae
5ad1193eb6 Create TW Icons by morosanuae.tid (#5495) 2021-02-13 20:16:06 +00:00
jeremy@jermolene.com
0ed32fded9 Freelinks: Add a filter for which tiddlers can be the targets of freelinks 2021-02-13 12:03:35 +00:00
jeremy@jermolene.com
50d0b6ee50 Modals: don't crash if options.event is missing
Raised here:

https://groups.google.com/d/msgid/tiddlywiki/3E83D2D3-42B2-4AA1-A042-52AB1D7B9B15%40gmail.com
2021-02-13 10:28:31 +00:00
Cameron Fischer
c0dc2669c0 Preallocating in LinkedList's toArray method (#5488) 2021-02-11 13:39:50 +00:00
jeremy@jermolene.com
40d21f607a Docs: Minor formatting tweaks
I was cloning this docs tiddler to experiment with docs for a new widget and noticed some punctuation inconsistencies
2021-02-07 12:48:06 +00:00
Joshua Fontany
bfa062f23d Fix filesystem (#5465) 2021-02-04 16:11:07 +00:00
jeremy@jermolene.com
9f9ce6595b Make it easier to subclass the wikitext parser with a custom rule set
We can now pass arrays of rule classes to the parser constructor, overriding the rules that would normally be used by the parser.

This allows us to create custom variants of the wikitext parser with their own content type.

It could also provide a basis for a new Markdown parser based on our existing wikitext parser but with new rules.
2021-02-03 15:13:56 +00:00
Simon Baird
12f1847475 Support upload saver without username/password (#5455)
The default behaviour is unchanged, but if you write "yes" to
$:/UploadWithUrlOnly then it will assume it's possible to upload
with a blank username and password, as long as the host is set.

The motivation is to support a upload plugin compatible upload
service that uses some method to authenticate other than the legacy
upload plugin user/password params.

Without this patch, the user would need to enter something random in
the user and password fields for TW to decide the upload plugin can
be used.
2021-01-31 15:32:18 +00:00
jeremy@jermolene.com
f2aba29d94 Update to KaTeX v0.12.0 2021-01-31 15:11:12 +00:00
Nicolas Petton
6a55069609 Fix the right margin of tags used outside of the tags wrapper (#5440) 2021-01-29 18:16:41 +00:00
Dyllon Gagnier
3eefb3cce6 Fix backtracking issue with regex (#5401)
There was an unnecessary
2021-01-29 15:26:25 +00:00
Dyllon Gagnier
2b41661721 Signing the CLA (#5445)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-29 15:25:43 +00:00
jeremy@jermolene.com
a360adbba9 Ensure dropzone is full size even if story river is empty
Thanks @jeremyredhead

Fixes #5446
2021-01-29 15:22:43 +00:00
Cameron Fischer
4c7dcb83d1 Fix for #3306, inline/block widget glitch (#5452)
* Fix for #3306, inline/block widget glitch

* Just realized we don't need to set lastIndex anymore

* Forgot that parseBlocks doesn't use options
2021-01-29 14:57:30 +00:00
Mario Pietsch
010158db81 Fix tiddler info area content bleeding on close animation (#5453) 2021-01-29 14:34:06 +00:00
Cameron Fischer
45355a7fcf Wikirules now use better macrocall parser (#5451)
* wikirules now use better macrocall parser

Before, wikirules would use a deficient macrocall parser which couldn't
handle certain types of arguments. Now it uses the same one that the
widget parser uses. Less code!

* style changes and removing weird switch statement

That switch statement made more sense in an earlier iteration.

* comment improvements

* oops, wikirule macrocalls could do ONE thing better

* '=' wasn't allowed for widget macros, but why?

Now they're allowed for both widget macros and macrocall macros.
2021-01-29 13:26:31 +00:00
jeremyredhead
f77015ea18 Signing the CLA (#5454) 2021-01-29 13:02:29 +00:00
jeremy@jermolene.com
8bab081c9e Remove illegal character from filename
Fixes #5430 for tiddlywiki-com branch
2021-01-27 17:21:25 +00:00
Joshua Fontany
4667139864 Rename TW5-firebase: TiddlyWiki5 for Google Firebase by Peter Neumark.tid (#5430)
* Delete TW5-firebase: TiddlyWiki5 for Google Firebase by Peter Neumark.tid

Delete file with illegal character in filename

* replace file without illegal character

* fixed ext
2021-01-27 17:18:54 +00:00
FlashSystems
2e47f277ac Fix blank favicon if root-tiddler=$:/core/save/lazy-images is set (#5423)
If image lazy loading is used with node.js the favicon is blank. The
line `-[!is[system]is[image]]` excludes only non system images from
begin saved as full tiddlers. But the `[is[image]]` line includes system
images as skinny tiddlers. The created HTML file has all system image
tiddlers (as the favicon) listed twice. And the skinny tiddler seems to
win in this case and breaks the display of the favicon.

This patch fixes this issue by excluding system images from the skinny
tiddlers list.
2021-01-21 17:07:28 +00:00
FlashSystems
ea12994f47 Signing the CLA (#5421)
...to contribute some code.

Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-21 17:07:13 +00:00
jeremy@jermolene.com
b4605e3573 Merge branch 'tiddlywiki-com' 2021-01-21 17:05:58 +00:00
jeremy@jermolene.com
674d55db06 Docs typo 2021-01-21 17:02:21 +00:00
leehawk787
678ec7b3dd Update Saving to a Git service.tid (#5427) 2021-01-21 17:00:38 +00:00
leehawk787
53ebfffedf Update cla-individual.md (#5426)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-21 16:59:39 +00:00
BlueGreenMagick
1ec532ea50 Update WikiRuleModules.tid (#5429) 2021-01-21 16:57:12 +00:00
BlueGreenMagick
3c3f1b60c6 Update cla-individual.md (#5428) 2021-01-21 16:56:12 +00:00
jeremy@jermolene.com
ae273a08f1 xlsx-utils: Fix demo spreadsheet
Somehow it had an error in it
2021-01-16 16:09:42 +00:00
jeremy@jermolene.com
36de5f65ff Core plugin images: Add missing classes 2021-01-16 15:39:05 +00:00
jeremy@jermolene.com
7be1e7e5f8 Xlsx-utils: Fix crash when using deserializer
Fixes #5400 (broken in #4601)
2021-01-16 15:37:50 +00:00
Nicolas Petton
b205da2007 Minor cleanup of startup.js (#5409)
* Remove unused var declaration
* Remove trailing whitespaces
2021-01-15 16:55:52 +00:00
Bram Chen
ffc8feea0c Update chinese help text for parameters of listen command (#5410)
* Improve help text for "csrf-disable"
* Add help text for "sse-enabled"
2021-01-15 16:54:03 +00:00
Peter Neumark
ce8c03250c Other Resources: fixed TW5-firebase URL (#5411) 2021-01-15 16:52:44 +00:00
Nicolas Petton
82b7167d55 Update the Notebook theme tiddler (#5387)
* Update the title to be shorter.
* Update the description to follow the description on
  https://nicolas.petton.fr/tw/notebook.html.
2021-01-15 12:20:55 +00:00
Nicolas Petton
afa490a0c1 Fix a typo in WebServer Parameter_ sse-enabled.tid (#5407) 2021-01-15 12:20:22 +00:00
Peter Neumark
8344d13efb Add TW5-firebase (#5408)
* Added resource tiddler for TW5-firebase

* Signing the CLA
2021-01-15 12:17:28 +00:00
Nicolas Petton
17b4f53ba2 Add server sent events (#5279)
* Create server-sent-events.js

* Create sse-change-listener.js

* Implement server sent events

* Convert to ES5 and wrap in function

* Use the host string from tiddlyweb

* Improve comments in sse-server.js

* Can't use object reference as key

* Add retry timeout

* Fix a bug

* bug fix

* Fix formatting

* Fix ES5 compat

* capitalize comments

* more fixes

* Refactor tiddlywek/sse-server.js

* Extract helper functions for handling wikis and connections.
* Replace JSDoc comments.
* Fix formatting according to TW core.
* Simplify the logic for adding and removing connections.

* Fix formatting of tiddlyweb/sse-client.js

Fix formatting according to TW core.

* Fix formatting of server-sent-events.js

Fix formatting and comments following TW core guidelines.

* Extract a debounce function in sse-client.js

* Avoid using startsWith in server-sent-events.js

startsWith is part of ES2015, while TiddlyWiki uses the 5.1 dialect.

* New sse-enabled WebServer parameter

* If not set to "yes", disabled SSE request handling.
* Add documentation for the parameter in core/language/en-GB/Help/listen.tid
* Add new tiddler editions/tw5.com/tiddlers/webserver/WebServer Parameter_ sse-enabled.tid

* Disable polling for changes if SSE is enabled

* Add sse_enabled to /status JSON response
* Store syncer polling status in $:/config/SyncDisablePolling
* Handled disabling polling in core/modules/syncer.js

* Simply boolean logic in syncer.js

* Delete trailing whitespaces in syncer.js

Co-authored-by: Arlen22 <arlenbee@gmail.com>
2021-01-15 10:37:55 +00:00
Nicolas Petton
a8457f7f9e Add a community resource tiddler documenting Projectify (#5372) 2021-01-13 12:51:48 +00:00
jeremy@jermolene.com
ca95f1069f Fixed comment parsers to match end marker correctly
Fixes #5396
2021-01-13 11:48:42 +00:00
Nicolas Petton
65ffe96cc2 Fix broken aria-label in $:/PaletteManager (#5397) 2021-01-13 10:18:27 +00:00
Cameron Fischer
b8a9826f23 Cleaned up jasmine test suite output (#5377)
* Cleaned up jasmine test suite output

Also testing for expected log messages, instead of just letting them print
to the console every single time, constantly making you think there's some
warning you need to worry about, and making all those dots not line up nicely.

* switched single quotes to double in collectLogs
2021-01-09 20:53:17 +00:00
Cameron Fischer
65932a9b21 Memory efficient linked list (#5380)
* Outlines of the mem efficient linked list

Need to stop for now. Found problem with $tw.utils.pushTop that I need
consultation for.

* Link list throws when given non-string vals

* Think I got rid of the last LinkList infinite loops

* LinkedList push better; fixed coding conventions

* Cleaning up LinkedList code and tests

* Ready to ship new mem efficient Linked List

* Switching to double quotes in LinkedList
2021-01-09 20:52:34 +00:00
jeremy@jermolene.com
af897361c7 Fix name of default branch for GitHub saver
Fixes #5317

Missed off 8cd13e2f89
2021-01-09 13:34:21 +00:00
Simon Huber
4858b24cfe Fix #5308 - WidgetSubclassingMechanism not working with widgets that add EventListeners (or logic ?) in constructor (#5382)
* add EventListeners in the render() method instead of the constructor

* scrollable widget: add EventListeners in render() method instead of constructor +

... move logic from constructor to render()

* linkcatcher: add EventListeners in render() instead of constructor

* fieldmangler: add EventListeners in render() instead of constructor

* edit-bitmap: initialise editorOperations in render() instead of constructor

* list-widget: initialise storyviews in render() instead of constructor

* vars widget: execute Widget.call(this) in render() instead of constructor

... not shure what this should do

* Update fieldmangler.js

* Update edit-bitmap.js

* Update linkcatcher.js

* Update navigator.js

* Update scrollable.js

* Update list.js

* Update vars.js
2021-01-09 13:25:48 +00:00
CodaCoder
5125b91b3f Update Formatting List Results as Tables with CSS - Specified Columns Methods.tid (#5375)
-moz-column* seems to have been dropped in Firefox. Added the non-prefixed, standard properties.
2021-01-07 18:22:05 +00:00
Cameron Fischer
b632cea6b7 Fixed issue where [lookup[]] could emit undefined (#5376) 2021-01-07 18:19:50 +00:00
jeremy@jermolene.com
eadbd62e6d Fix "modified" dates for tiddlers modified in #5353 2021-01-06 15:12:05 +00:00
Cameron Fischer
e280f89ca5 Converting [links[]] to use better LinkedList (#5369) 2021-01-05 17:36:18 +00:00
Mohammad Rahmani
87b9dbcda1 Remove extra dashes in page title (#5370)
When Tiddlywiki has no subtitle you see extra dashes!
2021-01-05 17:35:26 +00:00
donmor
5832002feb Docs: Create Japanese (Japan) Edition.tid (#5324)
Added the Japanese version tiddler since the Japanese version of empty.html exists
2021-01-04 11:05:41 +00:00
jeremy@jermolene.com
6a98106679 Update styles docs
Fixes #1691
2021-01-04 09:15:28 +00:00
CodaCoder
d5175e4fdc Update EventCatcherWidget.tid (#5335)
* Update EventCatcherWidget.tid

Changed "JavaScript events" to "DOM-initiated Javascript events". 
Removed the quotes from `"event"`. 
Tightened up some of the language.

* Update EventCatcherWidget.tid

Edited/reworded as per discussion(s).
2021-01-04 08:40:35 +00:00
CodaCoder
58010e089f Signed CLA (#5363) 2021-01-04 08:39:41 +00:00
Chris Nicoll
6edcbfd0cd Fix typos and Refnotes URL in kookma resources (#5365)
Co-authored-by: clutterstack <clutterstack@gmail.com>
2021-01-04 08:39:14 +00:00
Cameron Fischer
be70e5851d Taking advantage of linkedLists in all operator (#5362)
* Taking advantage of linkedLists in all operator

* Test to confirm [all[]] with LinkList is the same
2021-01-04 08:38:50 +00:00
Mario Pietsch
6f62c4fc7f Add missing tags (#5360) 2021-01-03 19:29:17 +00:00
maki lam
4fe411be80 Signing the CLA (#5327)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-03 11:52:30 +00:00
Simon Huber
ac40ee4246 Fix #5318 - remove-tag-button not having the correct fill color (#5326) 2021-01-03 11:51:30 +00:00
Joshua Fontany
bbe94f3544 Cleaned up Customising Tiddler File Naming docs (#5320)
* cleaned up Customising Tiddler File Naming

* revereted to british customis*
2021-01-03 11:50:39 +00:00
Joshua Fontany
03626bc142 always test ext in tiddler title and remove it (#5329)
* always test ext in tiddler title and remove it

* patch custom ext length vulernability
2021-01-03 11:50:14 +00:00
Rob Hoelz
69e595abf9 Add docs on share plugin (#5331)
…and mention it in the "sharing tiddlers" tiddler
2021-01-03 11:48:17 +00:00
jeremy@jermolene.com
e96a54c753 TiddlyWebAdaptor: Don't crash if "etag" header is missing 2021-01-03 11:46:40 +00:00
Glenn Dixon
a8639c3129 Signing the CLA (#5358) 2021-01-03 11:37:28 +00:00
Chris Nicoll
3ae27cab9e Signed cla-individual (#5333)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-03 11:36:11 +00:00
jeremy@jermolene.com
9434e95396 Fix PETTIL url
Fixes #5348
2021-01-03 10:48:13 +00:00
jeremy@jermolene.com
fecf622616 It's 2021! 2021-01-03 10:05:02 +00:00
jeremy@jermolene.com
d25e540dd2 Add support for image/vnd.microsoft.icon content type
Fixes #5357
2021-01-03 10:04:52 +00:00
Odin
4ee3ded04a Fixed typo in Community.tid (#5356) 2021-01-03 09:51:20 +00:00
Odin
87704b1770 Tiddlywiki com - Update to the Community page (#5353)
* Replaced the 'resources' tab with: Editions, Plugin, Themes, Palettes, Other resources.

* Added tiddlers that lists the new categories to be used in the Community tabs tiddler

* Added three themes for in the Community Themes section of the community page.

* Added three community made edtitions to the Community Editions tabs of the community page.

* Removed David Giffords Obahiah by his request.

* Added two palettes into the Community Palettes tab.

* Changed the link of 'PETTIL - Forth for the Commodore PET' to webarchive as discussed in pull request #5116

* removed four tiddlers because of dead links.

* Changed the dead link in Tiddlydrive add-on by Joshua Stubbs to link to the projects github instead.

* Fixed titltes in the community tabs macro.

* Sorted all entries into their new categories, updates tags accordingly and moved tid files into new folders according to their new category.

* final edit for sorting
2021-01-02 20:46:19 +00:00
Odin
493b45706f Signing the CLA (#5347)
Co-authored-by: Jeremy Ruston <jeremy@jermolene.com>
2021-01-02 17:52:53 +00:00
Joe Bordes
0ea89970d1 Doc(Developer) typo (#5354) 2021-01-02 17:39:46 +00:00
Joe Bordes
c2c8892aa5 Signing the CLA (#5355) 2021-01-02 17:38:51 +00:00
Jeremy Ruston
7ec6d37031 Fix filename of new release banner 2020-12-29 14:08:09 +00:00
Jeremy Ruston
24646e1993 Adjust placeholder release banner for readability 2020-12-29 13:27:00 +00:00
jeremy@jermolene.com
1e1b52088f Preparing for v5.1.24 as new prerelease
The new release banner is a placeholder; we'll run the competition once the release has taken shape a little.
2020-12-29 12:06:30 +00:00
714 changed files with 11982 additions and 5657 deletions

View File

@@ -23,6 +23,11 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**TiddlyWiki Configuration (please complete the following information):**
- Version [e.g. v5.1.24]
- Saving mechanism [e.g. Node.js, TiddlyDesktop, TiddlyHost etc]
- Plugins installed [e.g. Freelinks, TiddlyMap]
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]

View File

@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.1.23
TW5_BUILD_VERSION=v5.2.0
fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -107,7 +107,7 @@ node $TW5_BUILD_TIDDLYWIKI \
# /empty.html Empty
# /empty.hta For Internet Explorer
node $TW5_BUILD_TIDDLYWIKI \
./editions/empty \
$TW5_BUILD_MAIN_EDITION \
--verbose \
--output $TW5_BUILD_OUTPUT \
--build empty \

View File

@@ -5,52 +5,52 @@ Optimise the SVGs in ./core/images using SVGO from https://github.com/svg/svgo
Install SVGO with the following command in the root of the repo:
npm install svgo
npm install svgo@2.3.0
*/
"use strict";
var fs = require("fs"),
path = require("path"),
SVGO = require("svgo"),
svgo = new SVGO({
{ optimize } = require("svgo"),
config = {
plugins: [
{cleanupAttrs: true},
{removeDoctype: true},
{removeXMLProcInst: true},
{removeComments: true},
{removeMetadata: true},
{removeTitle: true},
{removeDesc: true},
{removeUselessDefs: true},
{removeEditorsNSData: true},
{removeEmptyAttrs: true},
{removeHiddenElems: true},
{removeEmptyText: true},
{removeEmptyContainers: true},
{removeViewBox: false},
{cleanupEnableBackground: true},
{convertStyleToAttrs: true},
{convertColors: true},
{convertPathData: true},
{convertTransform: true},
{removeUnknownsAndDefaults: true},
{removeNonInheritableGroupAttrs: true},
{removeUselessStrokeAndFill: true},
{removeUnusedNS: true},
{cleanupIDs: true},
{cleanupNumericValues: true},
{moveElemsAttrsToGroup: true},
{moveGroupAttrsToElems: true},
{collapseGroups: true},
{removeRasterImages: false},
{mergePaths: true},
{convertShapeToPath: true},
{sortAttrs: true},
{removeDimensions: false},
{removeAttrs: {attrs: "(stroke|fill)"}}
'cleanupAttrs',
'removeDoctype',
'removeXMLProcInst',
'removeComments',
'removeMetadata',
'removeTitle',
'removeDesc',
'removeUselessDefs',
'removeEditorsNSData',
'removeEmptyAttrs',
'removeHiddenElems',
'removeEmptyText',
'removeEmptyContainers',
// 'removeViewBox',
'cleanupEnableBackground',
'convertStyleToAttrs',
'convertColors',
'convertPathData',
'convertTransform',
'removeUnknownsAndDefaults',
'removeNonInheritableGroupAttrs',
'removeUselessStrokeAndFill',
'removeUnusedNS',
'cleanupIDs',
'cleanupNumericValues',
'moveElemsAttrsToGroup',
'moveGroupAttrsToElems',
'collapseGroups',
// 'removeRasterImages',
'mergePaths',
'convertShapeToPath',
'sortAttrs',
//'removeDimensions',
{name: 'removeAttrs', params: { attrs: '(stroke|fill)' } }
]
});
};
var basepath = "./core/images/",
files = fs.readdirSync(basepath).sort();
@@ -66,12 +66,14 @@ files.forEach(function(filename) {
fakeSVG = body.join("\n");
// A hack to make the new-journal-button work
fakeSVG = fakeSVG.replace("<<now \"DD\">>","&lt;&lt;now &quot;DD&quot;&gt;&gt;");
svgo.optimize(fakeSVG, {path: filepath}).then(function(result) {
config.path = filepath;
var result = optimize(fakeSVG,config);
if(result) {
var newSVG = header.join("\n") + "\n\n" + result.data.replace("&lt;&lt;now &quot;DD&quot;&gt;&gt;","<<now \"DD\">>");
fs.writeFileSync(filepath,newSVG);
},function(err) {
} else {
console.log("Error " + err + " with " + filename)
process.exit();
});
};
}
});

View File

@@ -757,7 +757,12 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
tiddler = $tw.wiki.getTiddler(name),
_exports = {},
sandbox = {
module: {exports: _exports},
module: {
exports: _exports,
setStringHandler: function(handler) {
moduleInfo.stringHandler = handler;
}
},
//moduleInfo: moduleInfo,
exports: _exports,
console: console,
@@ -821,7 +826,7 @@ $tw.modules.execute = function(moduleName,moduleRoot) {
moduleInfo.definition(moduleInfo,moduleInfo.exports,sandbox.require);
} else if(typeof moduleInfo.definition === "string") { // String
moduleInfo.exports = _exports;
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title);
$tw.utils.evalSandboxed(moduleInfo.definition,sandbox,name);
if(sandbox.module.exports) {
moduleInfo.exports = sandbox.module.exports; //more codemirror workaround
}
@@ -892,6 +897,19 @@ $tw.modules.applyMethods = function(moduleType,targetObject) {
return targetObject;
};
/*
Return a class created from a modules. The module should export the properties to be added to those of the optional base class
*/
$tw.modules.createClassFromModule = function(moduleExports,baseClass) {
var newClass = function() {};
if(baseClass) {
newClass.prototype = new baseClass();
newClass.prototype.constructor = baseClass;
}
$tw.utils.extend(newClass.prototype,moduleExports);
return newClass;
};
/*
Return an array of classes created from the modules of a specified type. Each module should export the properties to be added to those of the optional base class
*/
@@ -899,18 +917,26 @@ $tw.modules.createClassesFromModules = function(moduleType,subType,baseClass) {
var classes = Object.create(null);
$tw.modules.forEachModuleOfType(moduleType,function(title,moduleExports) {
if(!subType || moduleExports.types[subType]) {
var newClass = function() {};
if(baseClass) {
newClass.prototype = new baseClass();
newClass.prototype.constructor = baseClass;
}
$tw.utils.extend(newClass.prototype,moduleExports);
classes[moduleExports.name] = newClass;
classes[moduleExports.name] = $tw.modules.createClassFromModule(moduleExports,baseClass);
}
});
return classes;
};
/*
Return a specified module string for a module, null if the module or string is missing
*/
$tw.modules.getModuleString = function(moduleName,stringName,language) {
if(moduleName in $tw.modules.titles) {
$tw.modules.execute(moduleName);
var stringHandler = $tw.modules.titles[moduleName].stringHandler;
if(stringHandler) {
return stringHandler(stringName,language);
}
}
return null;
};
/////////////////////////// Barebones tiddler object
/*
@@ -1147,7 +1173,7 @@ $tw.Wiki = function(options) {
var index = tiddlerTitles.indexOf(title);
if(index !== -1) {
tiddlerTitles.splice(index,1);
}
}
}
// Record the new tiddler state
updateDescriptor["new"] = {
@@ -1294,7 +1320,7 @@ $tw.Wiki = function(options) {
}
} else {
if(pluginInfo[title]) {
delete pluginInfo[title];
delete pluginInfo[title];
results.deletedPlugins.push(title);
}
}
@@ -1717,13 +1743,20 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
},
t,result = [];
if(node) {
for(t = 0; t < node.childNodes.length; t++) {
var type = (node.getAttribute && node.getAttribute("type")) || null;
if(type) {
// A new-style container with an explicit deserialization type
result = $tw.wiki.deserializeTiddlers(type,node.textContent);
} else {
// An old-style container of classic DIV-based tiddlers
for(t = 0; t < node.childNodes.length; t++) {
var childNode = node.childNodes[t],
tiddlers = extractTextTiddlers(childNode);
tiddlers = tiddlers || extractModuleTiddlers(childNode);
if(tiddlers) {
result.push.apply(result,tiddlers);
}
}
}
}
return result;
@@ -1732,17 +1765,23 @@ $tw.modules.define("$:/boot/tiddlerdeserializer/dom","tiddlerdeserializer",{
$tw.loadTiddlersBrowser = function() {
// In the browser, we load tiddlers from certain elements
var containerIds = [
"libraryModules",
"modules",
"bootKernelPrefix",
"bootKernel",
"styleArea",
"storeArea",
"systemArea"
var containerSelectors = [
// IDs for old-style v5.1.x tiddler stores
"#libraryModules",
"#modules",
"#bootKernelPrefix",
"#bootKernel",
"#styleArea",
"#storeArea",
"#systemArea",
// Classes for new-style v5.2.x JSON tiddler stores
"script.tiddlywiki-tiddler-store"
];
for(var t=0; t<containerIds.length; t++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",document.getElementById(containerIds[t])));
for(var t=0; t<containerSelectors.length; t++) {
var nodes = document.querySelectorAll(containerSelectors[t]);
for(var n=0; n<nodes.length; n++) {
$tw.wiki.addTiddlers($tw.wiki.deserializeTiddlers("(DOM)",nodes[n]));
}
}
};
@@ -1933,7 +1972,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) {
}
} else {
console.log("Warning: a directory in a tiddlywiki.files file does not exist.");
console.log("dirPath: " + dirPath);
console.log("dirPath: " + dirPath);
console.log("tiddlywiki.files location: " + filepath);
}
}
@@ -1978,7 +2017,7 @@ $tw.loadPluginFolder = function(filepath,excludeRegExp) {
pluginInfo.dependents = pluginInfo.dependents || [];
pluginInfo.type = "application/json";
// Set plugin text
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers},null,4);
pluginInfo.text = JSON.stringify({tiddlers: pluginInfo.tiddlers});
delete pluginInfo.tiddlers;
// Deserialise array fields (currently required for the dependents field)
for(var field in pluginInfo) {
@@ -2126,6 +2165,7 @@ $tw.loadWikiTiddlers = function(wikiPath,options) {
fileInfo = $tw.boot.files[title];
if(fileInfo.isEditableFile) {
relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath);
fileInfo.originalpath = relativePath;
output[title] =
path.sep === "/" ?
relativePath :
@@ -2191,7 +2231,7 @@ $tw.loadTiddlersNode = function() {
type = parts[0];
if(parts.length === 3 && ["plugins","themes","languages"].indexOf(type) !== -1) {
$tw.loadPlugins([parts[1] + "/" + parts[2]],$tw.config[type + "Path"],$tw.config[type + "EnvVar"]);
}
}
}
});
// Load the tiddlers from the wiki directory
@@ -2301,6 +2341,7 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("image/heic","base64",".heic",{flags:["image"]});
$tw.utils.registerFileType("image/heif","base64",".heif",{flags:["image"]});
$tw.utils.registerFileType("image/svg+xml","utf8",".svg",{flags:["image"]});
$tw.utils.registerFileType("image/vnd.microsoft.icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("image/x-icon","base64",".ico",{flags:["image"]});
$tw.utils.registerFileType("application/font-woff","base64",".woff");
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
@@ -2458,16 +2499,29 @@ $tw.boot.executeNextStartupTask = function(callback) {
};
/*
Returns true if we are running on one platforms specified in a task modules `platforms` array
Returns true if we are running on one of the platforms specified in taskModule's
`platforms` array; or if `platforms` property is not defined.
*/
$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;
switch (platforms[t]) {
case "browser":
if ($tw.browser) {
return true;
}
break;
case "node":
if ($tw.node) {
return true;
}
break;
default:
$tw.utils.error("Module " + taskModule.name + ": '" + platforms[t] + "' in export.platforms invalid");
}
}
return false;
}
return true;
};

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@ type: text/plain
TiddlyWiki created by Jeremy Ruston, (jeremy [at] jermolene [dot] com)
Copyright (c) 2004-2007, Jeremy Ruston
Copyright (c) 2007-2020, UnaMesa Association
Copyright (c) 2007-2021, UnaMesa Association
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -0,0 +1,4 @@
title: $:/core/images/minus-button
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-minus-button tc-image-button" viewBox="0 0 128 128"><path d="M64 0c35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64C0 28.654 28.654 0 64 0zm.332 16c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"/><rect width="80" height="16" x="24" y="56" rx="8"/></svg>

View File

@@ -1,4 +1,4 @@
title: $:/core/images/plugin-generic-language
tags: $:/tags/Image
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-language tc-image-button"><path fill-rule="evenodd" d="M61.207 68.137c-4.324 2.795-6.999 6.656-6.999 10.921 0 7.906 9.19 14.424 21.042 15.336 2.162 3.902 8.598 6.785 16.318 7.01-5.126-1.125-9.117-3.742-10.62-7.01C92.805 93.487 102 86.967 102 79.059c0-8.53-10.699-15.445-23.896-15.445-6.599 0-12.572 1.729-16.897 4.524zm12.794-14.158c-4.324 2.795-10.298 4.524-16.897 4.524-2.619 0-5.14-.272-7.497-.775-3.312 2.25-8.383 3.69-14.067 3.69l-.255-.002c4.119-.892 7.511-2.747 9.478-5.13-6.925-2.704-11.555-7.617-11.555-13.228 0-8.53 10.699-15.445 23.896-15.445C70.301 27.613 81 34.528 81 43.058c0 4.265-2.675 8.126-6.999 10.921zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>

View File

@@ -1,4 +1,4 @@
title: $:/core/images/plugin-generic-plugin
tags: $:/tags/Image
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-plugin tc-image-button"><path fill-rule="evenodd" d="M40.397 76.446V95.34h14.12l-.001-.005a6.912 6.912 0 005.364-11.593l.046-.023a6.912 6.912 0 119.979.526l.086.055a6.914 6.914 0 004.408 10.948l-.023.092h21.32V75.568l-.15.038a6.912 6.912 0 00-11.593-5.364l-.022-.046a6.912 6.912 0 11.526-9.979l.055-.086a6.914 6.914 0 0010.948-4.408c.079.018.158.038.236.059v-15.74h-21.32l.023-.094a6.914 6.914 0 01-4.408-10.947 10.23 10.23 0 00-.086-.055 6.912 6.912 0 10-9.979-.526l-.046.023a6.912 6.912 0 01-5.364 11.593l.001.005h-14.12v12.847A6.912 6.912 0 0129.5 59.843l-.054.086a6.912 6.912 0 10-.526 9.979l.023.046a6.912 6.912 0 0111.455 6.492zM64 0l54.56 32v64L64 128 9.44 96V32L64 0z"/></svg>

View File

@@ -1,4 +1,4 @@
title: $:/core/images/plugin-generic-theme
tags: $:/tags/Image
<svg width="22pt" height="22pt" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z"/></svg>
<svg width="22pt" height="22pt" viewBox="0 0 128 128" class="tc-image-plugin-generic-theme tc-image-button"><path fill-rule="evenodd" d="M29.408 91.472L51.469 69.41l-.004-.005a2.22 2.22 0 01.004-3.146c.87-.87 2.281-.872 3.147-.005l9.465 9.464a2.22 2.22 0 01-.005 3.147c-.87.87-2.28.871-3.147.005l-.005-.005-22.061 22.062a6.686 6.686 0 11-9.455-9.455zM60.802 66.38c-2.436-2.704-4.465-5.091-5.817-6.869-6.855-9.014-10.313-4.268-14.226 0-3.913 4.268 1.03 7.726-2.683 10.741-3.713 3.015-3.484 4.06-9.752-1.455-6.267-5.516-6.7-7.034-3.823-10.181 2.877-3.147 5.281 1.808 11.159-3.785 5.877-5.593.94-10.55.94-10.55s12.237-25.014 28.588-23.167c16.351 1.848-6.186-2.392-11.792 17.226-2.4 8.4.447 6.42 4.998 9.968 1.394 1.086 6.03 4.401 11.794 8.685l20.677-20.676 1.615-4.766 7.84-4.689 3.151 3.152-4.688 7.84-4.766 1.615-20.224 20.223c12.663 9.547 28.312 22.146 28.312 26.709 0 7.217-3.071 11.526-9.535 9.164-4.693-1.715-18.768-15.192-28.753-25.897l-2.893 2.893-3.151-3.152 3.029-3.029zM63.953 0l54.56 32v64l-54.56 32-54.56-32V32l54.56-32z"/></svg>

View File

@@ -0,0 +1,4 @@
title: $:/core/images/plus-button
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-plus-button tc-image-button" viewBox="0 0 128 128"><path d="M64-.333c35.346 0 64 28.654 64 64 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64zM64 16c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"/><rect width="80" height="16" x="24" y="56" rx="8"/><rect width="16" height="80" x="56" y="24" rx="8"/></svg>

7
core/images/publish.tid Normal file
View File

@@ -0,0 +1,7 @@
title: $:/core/images/publish
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-publish tc-image-button" viewBox="0 0 128 128"><g fill-rule="evenodd">
<path d="M64.0434107,46.2358498 C65.8048912,45.8955184 67.6195684,46.7809274 68.4102078,48.4458716 L68.4937877,48.6340507 L98.8972485,122.034498 C99.7426494,124.075476 98.7734424,126.415349 96.7324641,127.26075 C94.7552664,128.079732 92.4975633,127.195747 91.5897922,125.284145 L91.5062123,125.095966 L88.403,117.605598 L79.5048497,126.50485 C78.775871,127.233828 77.8355254,127.622617 76.8810886,127.671216 L76.6764226,127.676423 C75.6527333,127.676423 74.6290441,127.285898 73.8479955,126.50485 L63.999,116.656598 L54.1520045,126.50485 C53.4230259,127.233828 52.4826802,127.622617 51.5282434,127.671216 L51.3235774,127.676423 C50.2998881,127.676423 49.2761989,127.285898 48.4951503,126.50485 L39.596,117.605598 L36.4937877,125.095966 C35.6483868,127.136944 33.3085142,128.106151 31.2675359,127.26075 C29.2265576,126.415349 28.2573506,124.075476 29.1027515,122.034498 L59.5062123,48.6340507 C60.2518688,46.8338766 62.1601511,45.867488 64.0005148,46.2445933 L64.0434107,46.2358498 Z M77.679,102.976598 L69.656,110.999598 L76.676,118.018598 L84.699,109.996598 L77.679,102.976598 Z M50.326,102.983598 L43.307,110.002598 L51.323,118.018598 L58.342,110.999598 L50.326,102.983598 Z M64.006,89.3035977 L55.983,97.3265977 L63.999,105.342598 L72.022,97.3195977 L64.006,89.3035977 Z M55.035,80.3325977 L50.348,91.6475977 L58.349,83.6465977 L55.035,80.3325977 Z M72.968,80.3415977 L69.663,83.6465977 L77.642,91.6255977 L72.968,80.3415977 Z M64,58.6895977 L58.3344072,72.3699713 C58.4295481,72.4423583 58.5221874,72.5195778 58.6119911,72.6016299 L58.7445283,72.7283325 L64.006,77.9895977 L69.2684411,72.7283325 C69.3957231,72.6010505 69.5294489,72.4841397 69.6685683,72.3775999 L64,58.6895977 Z M38.5026635,2.59571369 C40.7118025,2.59571369 42.5026635,4.38657469 42.5026635,6.59571369 C42.5026635,7.7643162 42.0015346,8.8158738 41.2024517,9.54721162 L41.372583,9.372583 C35.581722,15.163444 32,23.163444 32,32 C32,40.8370609 35.5821314,48.8374703 41.3735757,54.6284097 C42.0884306,55.3520538 42.531226,56.3471171 42.531226,57.4456008 C42.531226,59.6547398 40.740365,61.4456008 38.531226,61.4456008 C37.4327422,61.4456008 36.4376789,61.0028055 35.7147885,60.2859673 L35.7048234,60.2963403 C28.472656,53.0586276 24,43.0631255 24,32.0229786 C24,21.1046577 28.3744907,11.2080539 35.4664167,3.99022262 C36.2004724,3.13678606 37.2883808,2.59571369 38.5026635,2.59571369 Z M89.3688013,2.48959773 C90.5097745,2.48959773 91.5391719,2.96731026 92.2678917,3.73363348 L92.2733617,3.72780197 C99.5183488,10.9672382 104,20.9717355 104,32.0229786 C104,42.8488024 99.6993143,52.6701472 92.7132398,59.8717162 C91.9816831,60.8152368 90.8371876,61.4223982 89.5508819,61.4223982 C87.3417429,61.4223982 85.5508819,59.6315372 85.5508819,57.4223982 C85.5508819,56.3502862 85.9726717,55.3766885 86.6593633,54.6584932 L86.627417,54.627417 C92.418278,48.836556 96,40.836556 96,32 C96,23.2702193 92.5043135,15.3568999 86.8363661,9.5834674 C85.9399594,8.85136737 85.3688013,7.73718311 85.3688013,6.48959773 C85.3688013,4.28045873 87.1596623,2.48959773 89.3688013,2.48959773 Z M50.0871028,13.6297119 C52.2962418,13.6297119 54.0871028,15.4205729 54.0871028,17.6297119 C54.0871028,18.8506134 53.5401157,19.9437593 52.6778337,20.6774573 L52.6862915,20.6862915 C49.790861,23.581722 48,27.581722 48,32 C48,36.4187838 49.791271,40.4191937 52.6872859,43.3147028 L52.6777105,43.3251493 C53.4423082,44.0537041 53.918794,45.0819221 53.918794,46.2214294 C53.918794,48.4305684 52.127933,50.2214294 49.918794,50.2214294 C48.6900999,50.2214294 47.5907975,49.6674376 46.8570439,48.7956109 L47.0304281,48.9715536 C42.6867001,44.6283295 40,38.627921 40,32 C40,25.372583 42.6862915,19.372583 47.0294373,15.0294373 L47.0395567,15.0387468 C47.7732533,14.1766 48.8663118,13.6297119 50.0871028,13.6297119 Z M77.9823819,13.700452 C79.1679628,13.700452 80.2330731,14.2162483 80.9655529,15.0356811 L80.9715536,15.0304281 C85.314117,19.3734956 88,25.373087 88,32 C88,38.4619387 85.4461804,44.3274009 81.2927766,48.6421512 L80.9933974,48.9476975 C80.2638884,49.7186971 79.2309977,50.2000547 78.08568,50.2000547 C75.876541,50.2000547 74.08568,48.4091937 74.08568,46.2000547 C74.08568,45.0665777 74.557136,44.0432152 75.314649,43.3153662 L75.3137085,43.3137085 C78.209139,40.418278 80,36.418278 80,32 C80,27.5822253 78.209547,23.5826334 75.314698,20.6872811 C74.4981782,19.9511432 73.9823819,18.8860329 73.9823819,17.700452 C73.9823819,15.491313 75.7732429,13.700452 77.9823819,13.700452 Z M64,24 C68.418278,24 72,27.581722 72,32 C72,36.418278 68.418278,40 64,40 C59.581722,40 56,36.418278 56,32 C56,27.581722 59.581722,24 64,24 Z"></path>
</g>
</svg>

View File

@@ -32,6 +32,8 @@ ExportTiddler/Caption: export tiddler
ExportTiddler/Hint: Export tiddler
ExportTiddlers/Caption: export tiddlers
ExportTiddlers/Hint: Export tiddlers
ExportTiddlyWikiCore/Caption: export TiddlyWiki core
ExportTiddlyWikiCore/Hint: Export the ~TiddlyWiki core code for running with external ~JavaScript
SidebarSearch/Hint: Select the sidebar search field
Fold/Caption: fold tiddler
Fold/Hint: Fold the body of this tiddler
@@ -83,6 +85,8 @@ Permaview/Caption: permaview
Permaview/Hint: Set browser address bar to a direct link to all the tiddlers in this story
Print/Caption: print page
Print/Hint: Print the current page
Publish/Caption: publish
Publish/Hint: Publish from the wiki
Refresh/Caption: refresh
Refresh/Hint: Perform a full refresh of the wiki
Save/Caption: ok

View File

@@ -96,6 +96,8 @@ Plugins/Updates/Caption: Updates
Plugins/Updates/Hint: Available updates to installed plugins
Plugins/Updates/UpdateAll/Caption: Update <<update-count>> plugins
Plugins/SubPluginPrompt: With <<count>> sub-plugins available
Publishing/Caption: Publishing
Publishing/Hint: Settings used for publishing extracts from this TiddlyWiki as separate files through a "publisher" module
Saving/Caption: Saving
Saving/DownloadSaver/AutoSave/Description: Permit automatic saving for the download saver
Saving/DownloadSaver/AutoSave/Hint: Enable Autosave for Download Saver
@@ -123,12 +125,12 @@ Saving/TiddlySpot/BackupDir: Backup Directory
Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel
Saving/TiddlySpot/Backups: Backups
Saving/TiddlySpot/Caption: ~TiddlySpot Saver
Saving/TiddlySpot/Description: These settings are only used when saving to http://tiddlyspot.com or a compatible remote server
Saving/TiddlySpot/Description: These settings are only used when saving to [[TiddlySpot|http://tiddlyspot.com]], [[TiddlyHost|https://tiddlyhost.com]], or a compatible remote server. See [[here|https://github.com/simonbaird/tiddlyhost/wiki/TiddlySpot-Saver-configuration-for-Tiddlyhost-and-Tiddlyspot]] for information on ~TiddlySpot and ~TiddlyHost saving configuration.
Saving/TiddlySpot/Filename: Upload Filename
Saving/TiddlySpot/Heading: ~TiddlySpot
Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.//
Saving/TiddlySpot/Password: Password
Saving/TiddlySpot/ReadOnly: The ~TiddlySpot service is currently only available in read-only form. Please see http://tiddlyspot.com/ for the latest details. The ~TiddlySpot saver can still be used to save to compatible servers.
Saving/TiddlySpot/ReadOnly: Note that [[TiddlySpot|http://tiddlyspot.com]] no longer allows the creation of new sites. For new sites, you can use [[TiddlyHost|https://tiddlyhost.com]], a new hosting service that replaces ~TiddlySpot.
Saving/TiddlySpot/ServerURL: Server URL
Saving/TiddlySpot/UploadDir: Upload Directory
Saving/TiddlySpot/UserName: Wiki Name

View File

@@ -23,6 +23,7 @@ tiddlerfield: Defines the behaviour of an individual tiddler field.
tiddlermethod: Adds methods to the `$tw.Tiddler` prototype.
upgrader: Applies upgrade processing to tiddlers during an upgrade/import.
utils: Adds methods to `$tw.utils`.
utils-browser: Adds browser-specific methods to `$tw.utils`.
utils-node: Adds Node.js-specific methods to `$tw.utils`.
widget: Widgets encapsulate DOM rendering and refreshing.
wikimethod: Adds methods to `$tw.Wiki`.

View File

@@ -3,6 +3,8 @@ title: $:/language/EditTemplate/
Body/External/Hint: This tiddler shows content stored outside of the main TiddlyWiki file. You can edit the tags and fields but cannot directly edit the content itself
Body/Placeholder: Type the text for this tiddler
Body/Preview/Type/Output: output
Body/Preview/Type/DiffShadow: differences from shadow (if any)
Body/Preview/Type/DiffCurrent: differences from current
Field/Remove/Caption: remove field
Field/Remove/Hint: Remove field
Field/Dropdown/Caption: field list

View File

@@ -19,9 +19,11 @@ All parameters are optional with safe defaults, and can be specified in any orde
* ''username'' - optional username for basic authentication
* ''password'' - optional password for basic authentication
* ''authenticated-user-header'' - optional name of header to be used for trusted authentication
* ''readers'' - comma separated list of principals allowed to read from this wiki
* ''writers'' - comma separated list of principals allowed to write to this wiki
* ''readers'' - comma-separated list of principals allowed to read from this wiki
* ''writers'' - comma-separated list of principals allowed to write to this wiki
* ''csrf-disable'' - set to "yes" to disable CSRF checks (defaults to "no")
* ''sse-enabled'' - set to "yes" to enable Server-sent events (defaults to "no")
* ''sitemap'' - optional sitemap describing how the tiddlers will be served. See [[Publishing]] for more details
* ''root-tiddler'' - the tiddler to serve at the root (defaults to "$:/core/save/all")
* ''root-render-type'' - the content type to which the root tiddler should be rendered (defaults to "text/plain")
* ''root-serve-type'' - the content type with which the root tiddler should be served (defaults to "text/html")
@@ -29,6 +31,7 @@ All parameters are optional with safe defaults, and can be specified in any orde
* ''tls-key'' - pathname of TLS key file (relative to wiki folder)
* ''debug-level'' - optional debug level; set to "debug" to view request details (defaults to "none")
* ''gzip'' - set to "yes" to enable gzip compression for some http endpoints (defaults to "no")
* ''use-browser-cache'' - set to "yes" to allow the browser to cache responses to save bandwidth (defaults to "no")
For information on opening up your instance to the entire local network, and possible security concerns, see the WebServer tiddler at TiddlyWiki.com.

View File

@@ -8,15 +8,15 @@ Optionally, the title of a template tiddler can be specified. In this case, inst
A name and value for an additional variable may optionally also be specified.
```
--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [<name>] [<value>]
--render <tiddler-filter> [<filename-filter>] [<render-type>] [<template>] [ [<name>] [<value>] ]*
```
* ''tiddler-filter'': A filter identifying the tiddler(s) to be rendered
* ''filename-filter'': Optional filter transforming tiddler titles into pathnames. If omitted, defaults to `[is[tiddler]addsuffix[.html]]`, which uses the unchanged tiddler title as the filename
* ''render-type'': Optional render type: `text/html` (the default) returns the full HTML text and `text/plain` just returns the text content (ie it ignores HTML tags and other unprintable material)
* ''template'': Optional template through which each tiddler is rendered
* ''name'': Name of optional variable
* ''value'': Value of optional variable
* ''name'': Name of optional variables
* ''value'': Value of optional variables
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.
@@ -24,8 +24,9 @@ Notes:
* The output directory is not cleared of any existing files
* Any missing directories in the path to the filename are automatically created.
* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--render "[[Motovun Jack.jpg]]"`
* When referring to a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets: `--render "[[Motovun Jack.jpg]]"`
* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being rendered, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`
* Multiple ''name''/''value'' pairs can be used to pass more than one variable
* The `--render` command is a more flexible replacement for both the `--rendertiddler` and `--rendertiddlers` commands, which are deprecated
Examples:

View File

@@ -16,7 +16,7 @@ Notes:
* The output directory is not cleared of any existing files
* Any missing directories in the path to the filename are automatically created.
* When saving a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets : `--save "[[Motovun Jack.jpg]]"`
* When saving a tiddler with spaces in its title, take care to use both the quotes required by your shell and also TiddlyWiki's double square brackets: `--save "[[Motovun Jack.jpg]]"`
* The filename filter is evaluated with the selected items being set to the title of the tiddler currently being saved, allowing the title to be used as the basis for computing the filename. For example `[encodeuricomponent[]addprefix[static/]]` applies URI encoding to each title, and then adds the prefix `static/`
* The `--save` command is a more flexible replacement for both the `--savetiddler` and `--savetiddlers` commands, which are deprecated

View File

@@ -1,7 +1,9 @@
title: $:/language/Import/
Editor/Import/Heading: Import images and insert them into the editor.
Imported/Hint: The following tiddlers were imported:
Listing/Cancel/Caption: Cancel
Listing/Cancel/Warning: Do you wish to cancel the import?
Listing/Hint: These tiddlers are ready to import:
Listing/Import/Caption: Import
Listing/Select/Caption: Select
@@ -22,7 +24,11 @@ Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugi
Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> not being newer than existing <<existing>>).
Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>.
Upgrader/State/Suppressed: Blocked temporary state tiddler.
Upgrader/System/Disabled: Disabled system tiddler.
Upgrader/System/Suppressed: Blocked system tiddler.
Upgrader/System/Warning: Core module tiddler.
Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable.
Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>.
Upgrader/Tiddler/Disabled: Disabled tiddler.
Upgrader/Tiddler/Selected: User selected.
Upgrader/Tiddler/Unselected: Unselected tiddler.

View File

@@ -24,7 +24,6 @@ Encryption/RepeatPassword: Repeat password
Encryption/PasswordNoMatch: Passwords do not match
Encryption/SetPassword: Set password
Error/Caption: Error
Error/EditConflict: File changed on server
Error/Filter: Filter error
Error/FilterSyntax: Syntax error in filter expression
Error/FilterRunPrefix: Filter Error: Unknown prefix for filter run
@@ -32,6 +31,9 @@ Error/IsFilterOperator: Filter Error: Unknown operand for the 'is' filter operat
Error/FormatFilterOperator: Filter Error: Unknown suffix for the 'format' filter operator
Error/LoadingPluginLibrary: Error loading plugin library
Error/NetworkErrorAlert: `<h2>''Network Error''</h2>It looks like the connection to the server has been lost. This may indicate a problem with your network connection. Please attempt to restore network connectivity before continuing.<br><br>''Any unsaved changes will be automatically synchronised when connectivity is restored''.`
Error/PutEditConflict: File changed on server
Error/PutForbidden: Permission denied
Error/PutUnauthorized: Authentication required
Error/RecursiveTransclusion: Recursive transclusion error in transclude widget
Error/RetrievingSkinny: Error retrieving skinny tiddler list
Error/SavingToTWEdit: Error saving to TWEdit
@@ -39,7 +41,6 @@ Error/WhileSaving: Error while saving
Error/XMLHttpRequest: XMLHttpRequest error code
InternalJavaScriptError/Title: Internal JavaScript Error
InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`)
LayoutSwitcher/Description: Open the layout switcher
LazyLoadingWarning: <p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p>
LoginToTiddlySpace: Login to TiddlySpace

View File

@@ -0,0 +1,5 @@
title: $:/language/Publishing/Modal
subtitle: Publishing: ''<$transclude field="caption"><$view field="title"/></$transclude>''
footer: <$button message="tm-close-tiddler">Cancel</$button>
Publishing <$text text=<<totalFiles>>/> files via the "{{!!publisher}}" publisher.

View File

@@ -154,7 +154,7 @@ Commander.prototype.extractNamedParameters = function(params,mandatoryParameters
if(errors.length > 0) {
return errors.join(" and\n");
} else {
return paramsByName;
return paramsByName;
}
};

View File

@@ -115,7 +115,7 @@ Command.prototype.fetchFile = function(url,options,callback,redirectCount) {
if(response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) {
return self.fetchFile(response.headers.location,options,callback,redirectCount + 1);
} else {
return callback("Error " + response.statusCode + " retrieving " + url)
return callback("Error " + response.statusCode + " retrieving " + url)
}
}
});

View File

@@ -0,0 +1,46 @@
/*\
title: $:/core/modules/commands/publish.js
type: application/javascript
module-type: command
Publish static files
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "publish",
synchronous: false
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 1) {
return "Missing filename filter";
}
var self = this,
wiki = this.commander.wiki,
jobTiddler = this.params[0],
variableList = this.params.slice(1),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.publisherHandler.publish(jobTiddler,this.callback,{commander: this.commander,variables: variables});
return null;
};
exports.Command = Command;
})();

View File

@@ -37,16 +37,16 @@ Command.prototype.execute = function() {
filenameFilter = this.params[1] || "[is[tiddler]addsuffix[.html]]",
type = this.params[2] || "text/html",
template = this.params[3],
varName = this.params[4],
varValue = this.params[5],
tiddlers = wiki.filterTiddlers(tiddlerFilter);
variableList = this.params.slice(4),
tiddlers = wiki.filterTiddlers(tiddlerFilter),
variables = Object.create(null);
while(variableList.length >= 2) {
variables[variableList[0]] = variableList[1];
variableList = variableList.slice(2);
}
$tw.utils.each(tiddlers,function(title) {
var parser = wiki.parseTiddler(template || title),
variables = {currentTiddler: title};
if(varName) {
variables[varName] = varValue || "";
}
var widgetNode = wiki.makeWidget(parser,{variables: variables}),
var parser = wiki.parseTiddler(template || title);
var widgetNode = wiki.makeWidget(parser,{variables: $tw.utils.extend({},variables,{currentTiddler: title})}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
var text = type === "text/html" ? container.innerHTML : container.textContent,

View File

@@ -36,7 +36,7 @@ Command.prototype.execute = function() {
filter = this.params[0],
template = this.params[1],
outputPath = this.commander.outputPath,
pathname = path.resolve(outputPath,this.params[2]),
pathname = path.resolve(outputPath,this.params[2]),
type = this.params[3] || "text/html",
extension = this.params[4] || ".html",
deleteDirectory = (this.params[5] || "").toLowerCase() !== "noclean",

View File

@@ -97,7 +97,7 @@ WikiFolderMaker.prototype.save = function() {
// A custom plugin
self.log("Processing custom plugin: " + title);
self.saveCustomPlugin(tiddler);
}
}
} else {
// Ordinary tiddler
self.saveTiddler("tiddlers",tiddler);
@@ -158,11 +158,25 @@ WikiFolderMaker.prototype.saveCustomPlugin = function(pluginTiddler) {
};
WikiFolderMaker.prototype.saveTiddler = function(directory,tiddler) {
var title = tiddler.fields.title, fileInfo, pathFilters, extFilters;
if(this.wiki.tiddlerExists("$:/config/FileSystemPaths")) {
pathFilters = this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n");
}
if(this.wiki.tiddlerExists("$:/config/FileSystemExtensions")) {
extFilters = this.wiki.getTiddlerText("$:/config/FileSystemExtensions","").split("\n");
}
var fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{
directory: path.resolve(this.wikiFolderPath,directory),
wiki: this.wiki
pathFilters: pathFilters,
extFilters: extFilters,
wiki: this.wiki,
fileInfo: {}
});
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
try {
$tw.utils.saveTiddlerToFileSync(tiddler,fileInfo);
} catch (err) {
console.log("SaveWikiFolder: Error saving file '" + fileInfo.filepath + "', tiddler: '" + tiddler.fields.title);
}
};
WikiFolderMaker.prototype.saveJSONFile = function(filename,json) {

View File

@@ -34,7 +34,7 @@ exports.htmlEntities = {quot:34, amp:38, apos:39, lt:60, gt:62, nbsp:160, iexcl:
exports.htmlVoidElements = "area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(",");
exports.htmlBlockElements = "address,article,aside,audio,blockquote,canvas,dd,div,dl,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,noscript,ol,output,p,pre,section,table,tfoot,ul,video".split(",");
exports.htmlBlockElements = "address,article,aside,audio,blockquote,canvas,dd,details,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,li,nav,ol,p,pre,section,summary,table,tfoot,ul,video".split(",");
exports.htmlUnsafeElements = "script".split(",");

View File

@@ -12,6 +12,124 @@ Functions to deserialise tiddlers from a block of text
/*global $tw: false */
"use strict";
exports["application/x-tiddler-html-div"] = function(text,fields) {
return [deserializeTiddlerDiv(text,fields)];
};
exports["application/json"] = function(text,fields) {
var incoming,
results = [];
try {
incoming = JSON.parse(text);
} catch(e) {
incoming = [{
title: "JSON error: " + e,
text: ""
}]
}
if(!$tw.utils.isArray(incoming)) {
incoming = [incoming];
}
for(var t=0; t<incoming.length; t++) {
var incomingFields = incoming[t],
fields = {};
for(var f in incomingFields) {
if(typeof incomingFields[f] === "string") {
fields[f] = incomingFields[f];
}
}
results.push(fields);
}
return results;
};
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
var results = [];
// Check if we've got an old-style store area
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
storeAreaMatch = storeAreaMarkerRegExp.exec(text);
if(storeAreaMatch) {
// If so, we've got tiddlers in classic TiddlyWiki format or unencrypted old-style TW5 format
results.push.apply(results,deserializeStoreArea(text,storeAreaMarkerRegExp.lastIndex,!!storeAreaMatch[1],fields));
}
// Check for new-style store areas
var newStoreAreaMarkerRegExp = /<script class="tiddlywiki-tiddler-store" type="([^"]*)">/gi,
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text),
haveHadNewStoreArea = !!newStoreAreaMatch;
while(newStoreAreaMatch) {
results.push.apply(results,deserializeNewStoreArea(text,newStoreAreaMarkerRegExp.lastIndex,newStoreAreaMatch[1],fields));
newStoreAreaMatch = newStoreAreaMarkerRegExp.exec(text);
}
// Return if we had either an old-style or a new-style store area
if(storeAreaMatch || haveHadNewStoreArea) {
return results;
}
// Otherwise, check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
};
function deserializeHtmlFile(text,fields) {
var result = {};
$tw.utils.each(fields,function(value,name) {
result[name] = value;
});
result.text = text;
result.type = "text/html";
return [result];
}
function deserializeNewStoreArea(text,storeAreaEnd,type,fields) {
var endOfScriptRegExp = /<\/script>/gi;
endOfScriptRegExp.lastIndex = storeAreaEnd;
var match = endOfScriptRegExp.exec(text);
if(match) {
var scriptContent = text.substring(storeAreaEnd,match.index);
return $tw.wiki.deserializeTiddlers(type,scriptContent);
} else {
return [];
}
}
function deserializeStoreArea(text,storeAreaEnd,isTiddlyWiki5,fields) {
var results = [],
endOfDivRegExp = /(<\/div>\s*)/gi,
startPos = storeAreaEnd,
defaultType = isTiddlyWiki5 ? undefined : "text/x-tiddlywiki";
endOfDivRegExp.lastIndex = startPos;
var match = endOfDivRegExp.exec(text);
while(match) {
var endPos = endOfDivRegExp.lastIndex,
tiddlerFields = deserializeTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
if(!tiddlerFields) {
break;
}
$tw.utils.each(tiddlerFields,function(value,name) {
if(typeof value === "string") {
tiddlerFields[name] = $tw.utils.htmlDecode(value);
}
});
if(tiddlerFields.text !== null) {
results.push(tiddlerFields);
}
startPos = endPos;
match = endOfDivRegExp.exec(text);
}
return results;
}
/*
Utility function to parse an old-style tiddler DIV in a *.tid file. It looks like this:
@@ -24,7 +142,7 @@ Note that the field attributes are HTML encoded, but that the body of the <PRE>
When these tiddler DIVs are encountered within a TiddlyWiki HTML file then the body is encoded in the usual way.
*/
var parseTiddlerDiv = function(text /* [,fields] */) {
var deserializeTiddlerDiv = function(text /* [,fields] */) {
// Slot together the default results
var result = {};
if(arguments.length > 1) {
@@ -67,106 +185,4 @@ var parseTiddlerDiv = function(text /* [,fields] */) {
return undefined;
};
exports["application/x-tiddler-html-div"] = function(text,fields) {
return [parseTiddlerDiv(text,fields)];
};
exports["application/json"] = function(text,fields) {
var incoming,
results = [];
try {
incoming = JSON.parse(text);
} catch(e) {
incoming = [{
title: "JSON error: " + e,
text: ""
}]
}
if(!$tw.utils.isArray(incoming)) {
incoming = [incoming];
}
for(var t=0; t<incoming.length; t++) {
var incomingFields = incoming[t],
fields = {};
for(var f in incomingFields) {
if(typeof incomingFields[f] === "string") {
fields[f] = incomingFields[f];
}
}
results.push(fields);
}
return results;
};
/*
Parse an HTML file into tiddlers. There are three possibilities:
# A TiddlyWiki classic HTML file containing `text/x-tiddlywiki` tiddlers
# A TiddlyWiki5 HTML file containing `text/vnd.tiddlywiki` tiddlers
# An ordinary HTML file
*/
exports["text/html"] = function(text,fields) {
// Check if we've got a store area
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
match = storeAreaMarkerRegExp.exec(text);
if(match) {
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
// First read the normal tiddlers
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
// Then any system tiddlers
var systemAreaMarkerRegExp = /<div id=["']?systemArea['"]?( style=["']?display:none;["']?)?>/gi,
sysMatch = systemAreaMarkerRegExp.exec(text);
if(sysMatch) {
results.push.apply(results,deserializeTiddlyWikiFile(text,systemAreaMarkerRegExp.lastIndex,!!sysMatch[1],fields));
}
return results;
} else {
// Check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
}
};
function deserializeHtmlFile(text,fields) {
var result = {};
$tw.utils.each(fields,function(value,name) {
result[name] = value;
});
result.text = text;
result.type = "text/html";
return [result];
}
function deserializeTiddlyWikiFile(text,storeAreaEnd,isTiddlyWiki5,fields) {
var results = [],
endOfDivRegExp = /(<\/div>\s*)/gi,
startPos = storeAreaEnd,
defaultType = isTiddlyWiki5 ? undefined : "text/x-tiddlywiki";
endOfDivRegExp.lastIndex = startPos;
var match = endOfDivRegExp.exec(text);
while(match) {
var endPos = endOfDivRegExp.lastIndex,
tiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields,{type: defaultType});
if(!tiddlerFields) {
break;
}
$tw.utils.each(tiddlerFields,function(value,name) {
if(typeof value === "string") {
tiddlerFields[name] = $tw.utils.htmlDecode(value);
}
});
if(tiddlerFields.text !== null) {
results.push(tiddlerFields);
}
startPos = endPos;
match = endOfDivRegExp.exec(text);
}
return results;
}
})();

View File

@@ -78,7 +78,7 @@ function FramedEngine(options) {
}
if(this.widget.isDisabled === "yes") {
this.domNode.setAttribute("disabled",true);
}
}
// Copy the styles from the dummy textarea
this.copyStyles();
// Add event listeners
@@ -88,6 +88,18 @@ function FramedEngine(options) {
{name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}
]);
// Add drag and drop event listeners if fileDrop is enabled
if(this.widget.isFileDropEnabled) {
$tw.utils.addEventListeners(this.domNode,[
{name: "dragenter",handlerObject: this.widget,handlerMethod: "handleDragEnterEvent"},
{name: "dragover",handlerObject: this.widget,handlerMethod: "handleDragOverEvent"},
{name: "dragleave",handlerObject: this.widget,handlerMethod: "handleDragLeaveEvent"},
{name: "dragend",handlerObject: this.widget,handlerMethod: "handleDragEndEvent"},
{name: "drop", handlerObject: this.widget,handlerMethod: "handleDropEvent"},
{name: "paste", handlerObject: this.widget,handlerMethod: "handlePasteEvent"},
{name: "click",handlerObject: this.widget,handlerMethod: "handleClickEvent"}
]);
}
// Insert the element into the DOM
this.iframeDoc.body.appendChild(this.domNode);
}
@@ -170,7 +182,7 @@ Handle a focus event
*/
FramedEngine.prototype.handleFocusEvent = function(event) {
if(this.widget.editCancelPopups) {
$tw.popup.cancel(0);
$tw.popup.cancel(0);
}
};

View File

@@ -103,7 +103,11 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
var tiddler = this.wiki.getTiddler(this.editTitle);
if(tiddler) {
// If we've got a tiddler, the value to display is the field string value
value = tiddler.getFieldString(this.editField);
if(tiddler.hasField(this.editField)) {
value = tiddler.getFieldString(this.editField);
} else {
value = this.editDefault || "";
}
if(this.editField === "text") {
type = tiddler.fields.type || "text/vnd.tiddlywiki";
}
@@ -182,6 +186,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
this.editRefreshTitle = this.getAttribute("refreshTitle");
this.editAutoComplete = this.getAttribute("autocomplete");
this.isDisabled = this.getAttribute("disabled","no");
this.isFileDropEnabled = this.getAttribute("fileDrop","no") === "yes";
// Get the default editor element tag and type
var tag,type;
if(this.editField === "text") {
@@ -213,7 +218,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
@@ -293,21 +298,89 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
Propogate keydown events to our container for the keyboard widgets benefit
*/
EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent("Events");
if(newEvent.initEvent) {
newEvent.initEvent("keydown", true, true);
}
newEvent.keyCode = event.keyCode;
newEvent.which = event.which;
newEvent.metaKey = event.metaKey;
newEvent.ctrlKey = event.ctrlKey;
newEvent.altKey = event.altKey;
newEvent.shiftKey = event.shiftKey;
var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent);
};
return EditTextWidget;
EditTextWidget.prototype.cloneEvent = function(event,propertiesToCopy) {
var propertiesToCopy = propertiesToCopy || [],
newEvent = this.document.createEventObject ? this.document.createEventObject() : this.document.createEvent("Events");
if(newEvent.initEvent) {
newEvent.initEvent(event.type, true, true);
}
$tw.utils.each(propertiesToCopy,function(prop){
newEvent[prop] = event[prop];
});
return newEvent;
};
EditTextWidget.prototype.dispatchDOMEvent = function(newEvent) {
var dispatchNode = this.engine.iframeNode || this.engine.parentNode;
return dispatchNode.dispatchEvent(newEvent);
};
/*
Propogate drag and drop events with File data to our container for the dropzone widgets benefit.
If there are no Files, let the browser handle it.
*/
EditTextWidget.prototype.handleDropEvent = function(event) {
if(event.dataTransfer.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
};
EditTextWidget.prototype.handlePasteEvent = function(event) {
if(event.clipboardData.files.length) {
event.preventDefault();
event.stopPropagation();
this.dispatchDOMEvent(this.cloneEvent(event,["clipboardData"]));
}
};
EditTextWidget.prototype.handleDragEnterEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
// Ignore excessive events fired by FF when entering and leaving text nodes in a text area.
if( event.relatedTarget && (event.relatedTarget.nodeType === 3 || event.target === event.relatedTarget)) {
return true;
}
event.preventDefault();
return this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
return true;
};
EditTextWidget.prototype.handleDragOverEvent = function(event) {
if($tw.utils.dragEventContainsFiles(event)) {
// Call preventDefault() in browsers that default to not allowing drop events on textarea
if($tw.browser.isFirefox || $tw.browser.isIE) {
event.preventDefault();
}
event.dataTransfer.dropEffect = "copy";
return this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
}
return true;
};
EditTextWidget.prototype.handleDragLeaveEvent = function(event) {
// Ignore excessive events fired by FF when entering and leaving text nodes in a text area.
if(event.relatedTarget && ((event.relatedTarget.nodeType === 3) || (event.target === event.relatedTarget))) {
return true;
}
event.preventDefault();
this.dispatchDOMEvent(this.cloneEvent(event,["dataTransfer"]));
};
EditTextWidget.prototype.handleDragEndEvent = function(event) {
this.dispatchDOMEvent(this.cloneEvent(event));
};
EditTextWidget.prototype.handleClickEvent = function(event) {
return !this.dispatchDOMEvent(this.cloneEvent(event));
};
return EditTextWidget;
}
exports.editTextWidgetFactory = editTextWidgetFactory;

View File

@@ -0,0 +1,23 @@
/*\
title: $:/core/modules/editor/operations/text/insert-text.js
type: application/javascript
module-type: texteditoroperation
Text editor operation insert text at the caret position. If there is a selection it is replaced.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports["insert-text"] = function(event,operation) {
operation.replacement = event.paramObject.text;
operation.cutStart = operation.selStart;
operation.cutEnd = operation.selEnd;
operation.newSelStart = operation.selStart + operation.replacement.length;
operation.newSelEnd = operation.newSelStart;
};
})();

View File

@@ -17,10 +17,21 @@ exports.filter = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var resultsToRemove = [];
results.each(function(result) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([result]),widget);
results.each(function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
default:
return widget.getVariable(name);
}
}
});
if(filtered.length === 0) {
resultsToRemove.push(result);
resultsToRemove.push(title);
}
});
results.remove(resultsToRemove);

View File

@@ -0,0 +1,39 @@
/*\
title: $:/core/modules/filterrunprefixes/map.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.map = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var inputTitles = results.toArray();
results.clear();
$tw.utils.each(inputTitles,function(title) {
var filtered = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
default:
return widget.getVariable(name);
}
}
});
results.push(filtered[0] || "");
});
}
}
};
})();

View File

@@ -19,30 +19,32 @@ exports.reduce = function(operationSubFunction,options) {
var index = 0;
results.each(function(title) {
var list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return widget.getVariable(name);
}
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
case "accumulator":
return "" + accumulator;
case "index":
return "" + index;
case "revIndex":
return "" + (results.length - 1 - index);
case "length":
return "" + results.length;
default:
return widget.getVariable(name);
}
});
}
});
if(list.length > 0) {
accumulator = "" + list[0];
}
++index;
});
results.clear();
results.push(accumulator);
results.push(accumulator);
}
}
};

View File

@@ -0,0 +1,60 @@
/*\
title: $:/core/modules/filterrunprefixes/sort.js
type: application/javascript
module-type: filterrunprefix
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter prefix function
*/
exports.sort = function(operationSubFunction,options) {
return function(results,source,widget) {
if(results.length > 0) {
var suffixes = options.suffixes,
sortType = (suffixes[0] && suffixes[0][0]) ? suffixes[0][0] : "string",
invert = suffixes[1] ? (suffixes[1].indexOf("reverse") !== -1) : false,
isCaseSensitive = suffixes[1] ? (suffixes[1].indexOf("casesensitive") !== -1) : false,
inputTitles = results.toArray(),
sortKeys = [],
indexes = new Array(inputTitles.length),
compareFn;
results.each(function(title) {
var key = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return widget.getVariable("currentTiddler");
default:
return widget.getVariable(name);
}
}
});
sortKeys.push(key[0] || "");
});
results.clear();
// Prepare an array of indexes to sort
for(var t=0; t<inputTitles.length; t++) {
indexes[t] = t;
}
// Sort the indexes
compareFn = $tw.utils.makeCompareFunction(sortType,{defaultType: "string", invert:invert, isCaseSensitive:isCaseSensitive});
indexes = indexes.sort(function(a,b) {
return compareFn(sortKeys[a],sortKeys[b]);
});
// Add to results in correct order
$tw.utils.each(indexes,function(index) {
results.push(inputTitles[index]);
});
}
}
};
})();

View File

@@ -63,7 +63,7 @@ function parseFilterOperation(operators,filterString,p) {
operator.operator = "title";
}
operator.operands = [];
function parseOperand(bracketType) {
var parseOperand = function(bracketType) {
var operand = {};
switch (bracketType) {
case "{": // Curly brackets
@@ -78,7 +78,7 @@ function parseFilterOperation(operators,filterString,p) {
nextBracketPos = filterString.indexOf(">",p);
break;
case "/": // regexp brackets
var rex = /^((?:[^\\\/]*|\\.)*)\/(?:\(([mygi]+)\))?/g,
var rex = /^((?:[^\\\/]|\\.)*)\/(?:\(([mygi]+)\))?/g,
rexMatch = rex.exec(filterString.substring(p));
if(rexMatch) {
operator.regexp = new RegExp(rexMatch[1], rexMatch[2]);
@@ -101,10 +101,10 @@ function parseFilterOperation(operators,filterString,p) {
}
p = nextBracketPos + 1;
}
p = nextBracketPos + 1;
parseOperand(bracket);
// Check for multiple operands
while(filterString.charAt(p) === ",") {
p++;
@@ -116,7 +116,7 @@ function parseFilterOperation(operators,filterString,p) {
throw "Missing [ in filter expression";
}
}
// Push this operator
operators.push(operator);
} while(filterString.charAt(p) !== "]");
@@ -137,7 +137,7 @@ exports.parseFilter = function(filterString) {
p = 0, // Current position in the filter string
match;
var whitespaceRegExp = /(\s+)/mg,
operandRegExp = /((?:\+|\-|~|=|\:(\w+))?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
operandRegExp = /((?:\+|\-|~|=|\:(\w+)(?:\:([\w\:, ]*))?)?)(?:(\[)|(?:"([^"]*)")|(?:'([^']*)')|([^\s\[\]]+))/mg;
while(p < filterString.length) {
// Skip any whitespace
whitespaceRegExp.lastIndex = p;
@@ -162,15 +162,27 @@ exports.parseFilter = function(filterString) {
if(match[2]) {
operation.namedPrefix = match[2];
}
if(match[3]) {
operation.suffixes = [];
$tw.utils.each(match[3].split(":"),function(subsuffix) {
operation.suffixes.push([]);
$tw.utils.each(subsuffix.split(","),function(entry) {
entry = $tw.utils.trim(entry);
if(entry) {
operation.suffixes[operation.suffixes.length -1].push(entry);
}
});
});
}
}
if(match[3]) { // Opening square bracket
if(match[4]) { // Opening square bracket
p = parseFilterOperation(operation.operators,filterString,p);
} else {
p = match.index + match[0].length;
}
if(match[4] || match[5] || match[6]) { // Double quoted string, single quoted string or unquoted title
if(match[5] || match[6] || match[7]) { // Double quoted string, single quoted string or unquoted title
operation.operators.push(
{operator: "title", operands: [{text: match[4] || match[5] || match[6]}]}
{operator: "title", operands: [{text: match[5] || match[6] || match[7]}]}
);
}
results.push(operation);
@@ -236,12 +248,13 @@ exports.compileFilter = function(filterString) {
} else {
operatorFunction = filterOperators[operator.operator];
}
$tw.utils.each(operator.operands,function(operand) {
if(operand.indirect) {
operand.value = self.getTextReference(operand.text,"",currTiddlerTitle);
} else if(operand.variable) {
operand.value = widget.getVariable(operand.text,{defaultValue: ""});
var varTree = $tw.utils.parseFilterVariable(operand.text);
operand.value = widget.getVariable(varTree.name,{params:varTree.params,defaultValue: ""});
} else {
operand.value = operand.text;
}
@@ -280,7 +293,7 @@ exports.compileFilter = function(filterString) {
var filterRunPrefixes = self.getFilterRunPrefixes();
// Wrap the operator functions in a wrapper function that depends on the prefix
operationFunctions.push((function() {
var options = {wiki: self};
var options = {wiki: self, suffixes: operation.suffixes || []};
switch(operation.prefix || "") {
case "": // No prefix means that the operation is unioned into the result
return filterRunPrefixes["or"](operationSubFunction, options);
@@ -311,6 +324,9 @@ exports.compileFilter = function(filterString) {
} else if(typeof source === "object") { // Array or hashmap
source = self.makeTiddlerIterator(source);
}
if(!widget) {
widget = $tw.rootWidget;
}
var results = new $tw.utils.LinkedList();
$tw.utils.each(operationFunctions,function(operationFunction) {
operationFunction(results,source,widget);

View File

@@ -31,7 +31,7 @@ exports.all = function(source,operator,options) {
// Get our suboperators
var allFilterOperators = getAllFilterOperators();
// Cycle through the suboperators accumulating their results
var results = [],
var results = new $tw.utils.LinkedList(),
subops = operator.operand.split("+");
// Check for common optimisations
if(subops.length === 1 && subops[0] === "") {
@@ -49,10 +49,10 @@ exports.all = function(source,operator,options) {
for(var t=0; t<subops.length; t++) {
var subop = allFilterOperators[subops[t]];
if(subop) {
$tw.utils.pushTop(results,subop(source,operator.prefix,options));
results.pushTop(subop(source,operator.prefix,options));
}
}
return results;
return results.toArray();
};
})();

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.contains = function(source,operator,options) {
var results = [],
fieldname = (operator.suffix || "list").toLowerCase();
fieldname = operator.suffix || "list";
if(operator.prefix === "!") {
source(function(tiddler,title) {
if(tiddler) {

View File

@@ -0,0 +1,27 @@
/*\
title: $:/core/modules/filters/deserializers.js
type: application/javascript
module-type: filteroperator
Filter operator for returning the names of the deserializers in this wiki
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.deserializers = function(source,operator,options) {
var results = [];
$tw.utils.each($tw.Wiki.tiddlerDeserializerModules,function(deserializer,type) {
results.push(type);
});
results.sort();
return results;
};
})();

View File

@@ -22,7 +22,7 @@ exports.editiondescription = function(source,operator,options) {
if(editionInfo) {
source(function(tiddler,title) {
if($tw.utils.hop(editionInfo,title)) {
results.push(editionInfo[title].description || "");
results.push(editionInfo[title].description || "");
}
});
}

View File

@@ -102,7 +102,7 @@ exports.escapecss = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
// escape any character with a special meaning in CSS using CSS.escape()
results.push(CSS.escape(title));
results.push($tw.utils.escapeCSS(title));
});
return results;
};

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.field = function(source,operator,options) {
var results = [],indexedResults,
fieldname = (operator.suffix || operator.operator || "title").toLowerCase();
fieldname = operator.suffix || operator.operator || "title";
if(operator.prefix === "!") {
if(operator.regexp) {
source(function(tiddler,title) {

View File

@@ -20,7 +20,7 @@ exports.fields = function(source,operator,options) {
fieldName,
suffixes = (operator.suffixes || [])[0] || [],
operand = $tw.utils.parseStringArray(operator.operand);
source(function(tiddler,title) {
if(tiddler) {
if(suffixes.indexOf("include") !== -1) {

View File

@@ -20,7 +20,18 @@ exports.filter = function(source,operator,options) {
results = [],
target = operator.prefix !== "!";
source(function(tiddler,title) {
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]));
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
getVariable: function(name) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});
if((list.length > 0) === target) {
results.push(title);
}

View File

@@ -13,13 +13,13 @@ module-type: formatfilteroperator
Export our filter function
*/
exports.date = function(source,operand,options) {
var results = [];
var results = [];
source(function(tiddler,title) {
var value = $tw.utils.parseDate(title);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
results.push($tw.utils.formatDateString(value,operand || "YYYY MM DD 0hh:0mm"));
}
});
});
return results;
};

View File

@@ -13,13 +13,13 @@ module-type: formatfilteroperator
Export our filter function
*/
exports.relativedate = function(source,operand,options) {
var results = [];
var results = [];
source(function(tiddler,title) {
var value = $tw.utils.parseDate(title);
if(value && $tw.utils.isDate(value) && value.toString() !== "Invalid Date") {
results.push($tw.utils.getRelativeDate((new Date()) - (new Date(value))).description);
}
});
});
return results;
};

View File

@@ -0,0 +1,25 @@
/*\
title: $:/core/modules/filters/format/titlelist.js
type: application/javascript
module-type: formatfilteroperator
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.titlelist = function(source,operand,options) {
var results = [];
source(function(tiddler,title) {
if(title && title.length) {
results.push($tw.utils.stringifyList([title]));
}
});
return results;
};
})();

View File

@@ -61,7 +61,7 @@ exports.has = function(source,operator,options) {
if(tiddler && $tw.utils.hop(tiddler.fields,operator.operand) && (tiddler.fields[operator.operand].length !== 0)) {
results.push(title);
}
});
});
}
}
return results;

View File

@@ -28,7 +28,7 @@ exports.draft = function(source,prefix,options) {
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.of") && (tiddler.fields["draft.of"].length !== 0)) {
results.push(title);
}
});
});
}
return results;
};

View File

@@ -16,11 +16,11 @@ Filter operator for returning all the links from a tiddler
Export our filter function
*/
exports.links = function(source,operator,options) {
var results = [];
var results = new $tw.utils.LinkedList();
source(function(tiddler,title) {
$tw.utils.pushTop(results,options.wiki.getTiddlerLinks(title));
results.pushTop(options.wiki.getTiddlerLinks(title));
});
return results;
return results.toArray();
};
})();

View File

@@ -22,7 +22,7 @@ Export our filter function
exports.lookup = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix);
results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix || '');
});
return results;
};

View File

@@ -125,6 +125,54 @@ exports.minall = makeNumericReducingOperator(
Infinity // Initial value
);
exports.median = makeNumericArrayOperator(
function(values) {
var len = values.length, median;
values.sort();
if(len % 2) {
// Odd, return the middle number
median = values[(len - 1) / 2];
} else {
// Even, return average of two middle numbers
median = (values[len / 2 - 1] + values[len / 2]) / 2;
}
return [median];
}
);
exports.average = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
0, // Initial value
function(finalValue,numberOfValues) {
return finalValue/numberOfValues;
}
);
exports.variance = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
0,
function(finalValue,numberOfValues,originalValues) {
return getVarianceFromArray(originalValues,finalValue/numberOfValues);
}
);
exports["standard-deviation"] = makeNumericReducingOperator(
function(accumulator,value) {return accumulator + value},
0,
function(finalValue,numberOfValues,originalValues) {
var variance = getVarianceFromArray(originalValues,finalValue/numberOfValues);
return Math.sqrt(variance);
}
);
//Calculate the variance of a population of numbers in an array given its mean
function getVarianceFromArray(values,mean) {
var deviationTotal = values.reduce(function(accumulator,value) {
return accumulator + Math.pow(value - mean, 2);
},0);
return deviationTotal/values.length;
};
function makeNumericBinaryOperator(fnCalc) {
return function(source,operator,options) {
var result = [],
@@ -134,19 +182,37 @@ function makeNumericBinaryOperator(fnCalc) {
});
return result;
};
}
};
function makeNumericReducingOperator(fnCalc,initialValue) {
function makeNumericReducingOperator(fnCalc,initialValue,fnFinal) {
initialValue = initialValue || 0;
return function(source,operator,options) {
var result = [];
source(function(tiddler,title) {
result.push(title);
result.push($tw.utils.parseNumber(title));
});
return [$tw.utils.stringifyNumber(result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,$tw.utils.parseNumber(currentValue));
},initialValue))];
var value = result.reduce(function(accumulator,currentValue) {
return fnCalc(accumulator,currentValue);
},initialValue);
if(fnFinal) {
value = fnFinal(value,result.length,result);
}
return [$tw.utils.stringifyNumber(value)];
};
}
};
function makeNumericArrayOperator(fnCalc) {
return function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push($tw.utils.parseNumber(title));
});
results = fnCalc(results);
$tw.utils.each(results,function(value,index) {
results[index] = $tw.utils.stringifyNumber(value);
});
return results;
};
};
})();

View File

@@ -0,0 +1,30 @@
/*\
title: $:/core/modules/filters/moduleproperty.js
type: application/javascript
module-type: filteroperator
Filter [[module-name]moduleproperty[name]] retrieve a module property
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.moduleproperty = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
var value = require(title)[operator.operand || ""];
if(value !== undefined) {
results.push(value);
}
});
results.sort();
return results;
};
})();

View File

@@ -17,11 +17,23 @@ Export our filter function
*/
exports.modules = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
results.push(moduleName);
if(operator.operands.length === 1) {
// Return all the module names without filtering
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
results.push(moduleName);
});
});
});
} else if(operator.operands.length >= 2) {
// Return the modules that have the module property specified in the first operand with the value in the second operand
source(function(tiddler,title) {
$tw.utils.each($tw.modules.types[title],function(moduleInfo,moduleName) {
if(require(moduleName)[operator.operands[0]] === operator.operands[1]) {
results.push(moduleName);
}
});
});
}
results.sort();
return results;
};

View File

@@ -0,0 +1,30 @@
/*\
title: $:/core/modules/filters/modulestring.js
type: application/javascript
module-type: filteroperator
Filter [[module-name]modulestring[en-gb]] retrieve a module strings in a particular language
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Export our filter function
*/
exports.modulestring = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
var s = $tw.modules.getModuleString(title,operator.operands[0] || "",operator.operands[1] || "");
if(s !== null) {
results.push(s);
}
});
results.sort();
return results;
};
})();

View File

@@ -31,6 +31,8 @@ exports.reduce = function(source,operator,options) {
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
case "accumulator":
return "" + accumulator;
case "index":

View File

@@ -17,7 +17,7 @@ Export our filter function
*/
exports.regexp = function(source,operator,options) {
var results = [],
fieldname = (operator.suffix || "title").toLowerCase(),
fieldname = operator.suffix || "title",
regexpString, regexp, flags = "", match,
getFieldString = function(tiddler,title) {
if(tiddler) {

View File

@@ -27,10 +27,13 @@ exports.sortsub = function(source,operator,options) {
iterator(options.wiki.getTiddler(title),title);
},{
getVariable: function(name) {
if(name === "currentTiddler") {
return title;
} else {
return options.widget.getVariable(name);
switch(name) {
case "currentTiddler":
return "" + title;
case "..currentTiddler":
return options.widget.getVariable("currentTiddler");
default:
return options.widget.getVariable(name);
}
}
});

View File

@@ -105,13 +105,13 @@ exports.splitregexp = function(source,operator,options) {
flags = (suffix.indexOf("m") !== -1 ? "m" : "") + (suffix.indexOf("i") !== -1 ? "i" : ""),
regExp;
try {
regExp = new RegExp(operator.operand || "",flags);
regExp = new RegExp(operator.operand || "",flags);
} catch(ex) {
return ["RegExp error: " + ex];
}
source(function(tiddler,title) {
Array.prototype.push.apply(result,title.split(regExp));
});
});
return result;
};
@@ -123,7 +123,7 @@ exports["search-replace"] = function(source,operator,options) {
isRegExp = (suffixes[1] && suffixes[1][0] === "regexp") ? true : false,
searchTerm,
regExp;
source(function(tiddler,title) {
if(title && (operator.operands.length > 1)) {
//Escape regexp characters if the operand is not a regular expression
@@ -156,7 +156,7 @@ exports.pad = function(source,operator,options) {
var padString = "",
padStringLength = targetLength - title.length;
while (padStringLength > padString.length) {
padString += fill;
padString += fill;
}
//make sure we do not exceed the specified length
padString = padString.slice(0,padStringLength);
@@ -172,4 +172,14 @@ exports.pad = function(source,operator,options) {
return results;
}
exports.charcode = function(source,operator,options) {
var chars = [];
$tw.utils.each(operator.operands,function(operand) {
if(operand !== "") {
chars.push(String.fromCharCode($tw.utils.parseInt(operand)));
}
});
return [chars.join("")];
};
})();

View File

@@ -50,7 +50,7 @@ exports.tag = function(source,operator,options) {
});
results = options.wiki.sortByList(results,operator.operand);
}
}
}
}
return results;
};

View File

@@ -193,7 +193,7 @@ Extended filter operators to manipulate the current list.
step = stepSize || 1,
i = 0,
opLength = operands.length,
nextOperandIndex;
nextOperandIndex;
for(i; i < opLength; i++) {
resultsIndex = results.indexOf(operands[i]);
if(resultsIndex !== -1) {
@@ -211,12 +211,12 @@ Extended filter operators to manipulate the current list.
} else {
results.push(operands[0]);
}
return results;
return results;
}
/*
Toggles an item in the current list.
*/
*/
exports.toggle = function(source,operator) {
return cycleValueInArray(prepare_results(source),operator.operands);
}
@@ -228,8 +228,8 @@ Extended filter operators to manipulate the current list.
if(step < 0) {
operands.reverse();
step = Math.abs(step);
}
}
return cycleValueInArray(results,operands,step);
}
})();

View File

@@ -121,7 +121,7 @@ FieldIndexer.prototype.update = function(updateDescriptor) {
indexEntry[value].push(updateDescriptor["new"].tiddler.fields.title);
}
}
});
});
}
};

View File

@@ -65,7 +65,7 @@ TagSubIndexer.prototype.rebuild = function() {
} else {
self.index[tag].titles.push(title);
}
});
});
});
};
@@ -83,7 +83,7 @@ TagSubIndexer.prototype.lookup = function(tag) {
if(!indexRecord.isSorted) {
if(this.indexer.wiki.sortByList) {
indexRecord.titles = this.indexer.wiki.sortByList(indexRecord.titles,tag);
}
}
indexRecord.isSorted = true;
}
return indexRecord.titles;

View File

@@ -22,7 +22,7 @@ exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) {
if($tw.browser) {
// Document location
var setLocationProperty = function(name,value) {
infoTiddlerFields.push({title: "$:/info/url/" + name, text: value});
infoTiddlerFields.push({title: "$:/info/url/" + name, text: value});
},
location = document.location;
setLocationProperty("full", (location.toString()).split("#")[0]);

View File

@@ -179,7 +179,7 @@ Key descriptors have the following format:
ctrl+enter
ctrl+shift+alt+A
*/
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {
KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor,options) {
var components = keyDescriptor.split(/\+|\-/),
info = {
keyCode: 0,
@@ -206,6 +206,9 @@ KeyboardManager.prototype.parseKeyDescriptor = function(keyDescriptor) {
info.keyCode = this.namedKeys[s];
}
}
if(options.keyDescriptor) {
info.keyDescriptor = options.keyDescriptor;
}
if(info.keyCode) {
return info;
} else {
@@ -237,6 +240,7 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
lookupName = function(configName) {
var keyDescriptors = wiki.getTiddlerText("$:/config/" + configName + "/" + name);
if(keyDescriptors) {
options.keyDescriptor = keyDescriptor;
result.push.apply(result,self.parseKeyDescriptors(keyDescriptors,options));
}
};
@@ -245,7 +249,7 @@ KeyboardManager.prototype.parseKeyDescriptors = function(keyDescriptors,options)
});
}
} else {
result.push(self.parseKeyDescriptor(keyDescriptor));
result.push(self.parseKeyDescriptor(keyDescriptor,options));
}
});
return result;
@@ -276,16 +280,20 @@ KeyboardManager.prototype.checkKeyDescriptor = function(event,keyInfo) {
};
KeyboardManager.prototype.checkKeyDescriptors = function(event,keyInfoArray) {
return (this.getMatchingKeyDescriptor(event,keyInfoArray) !== null);
};
KeyboardManager.prototype.getMatchingKeyDescriptor = function(event,keyInfoArray) {
for(var t=0; t<keyInfoArray.length; t++) {
if(this.checkKeyDescriptor(event,keyInfoArray[t])) {
return true;
return keyInfoArray[t];
}
}
return false;
return null;
};
KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
return event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? "ctrl" :
return event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey ? "ctrl" :
event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey ? "shift" :
event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey ? "ctrl-shift" :
event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey ? "alt" :
@@ -295,7 +303,7 @@ KeyboardManager.prototype.getEventModifierKeyDescriptor = function(event) {
event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey ? "meta" :
event.metaKey && event.ctrlKey && !event.shiftKey && !event.altKey ? "meta-ctrl" :
event.metaKey && event.ctrlKey && event.shiftKey && !event.altKey ? "meta-ctrl-shift" :
event.metaKey && event.ctrlKey & event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
event.metaKey && event.ctrlKey && event.shiftKey && event.altKey ? "meta-ctrl-alt-shift" : "normal";
};
KeyboardManager.prototype.getShortcutTiddlerList = function() {
@@ -324,7 +332,7 @@ KeyboardManager.prototype.handleKeydownEvent = function(event) {
if(key !== undefined) {
event.preventDefault();
event.stopPropagation();
$tw.rootWidget.invokeActionString(action,$tw.rootWidget);
$tw.rootWidget.invokeActionString(action,$tw.rootWidget,event);
return true;
}
return false;

View File

@@ -2,6 +2,7 @@
title: $:/core/modules/macros/unusedtitle.js
type: application/javascript
module-type: macro
Macro to return a new title that is unused in the wiki. It can be given a name as a base.
\*/
(function(){
@@ -10,25 +11,25 @@ Macro to return a new title that is unused in the wiki. It can be given a name a
/*global $tw: false */
"use strict";
/*
Information about this macro
*/
exports.name = "unusedtitle";
exports.params = [
{name: "baseName"},
{name: "options"}
{name: "separator"},
{name: "template"}
];
/*
Run the macro
*/
exports.run = function(baseName, options) {
exports.run = function(baseName,separator,template) {
separator = separator || " ";
if(!baseName) {
baseName = $tw.language.getString("DefaultNewTiddlerTitle");
}
return this.wiki.generateNewTitle(baseName, options);
// $tw.wiki.generateNewTitle = function(baseTitle,options)
// options.prefix must be a string!
return this.wiki.generateNewTitle(baseName, {"prefix": separator, "template": template});
};
})();

View File

@@ -23,10 +23,12 @@ var HtmlParser = function(type,text,options) {
type: "element",
tag: "iframe",
attributes: {
src: {type: "string", value: src},
sandbox: {type: "string", value: ""}
src: {type: "string", value: src}
}
}];
if($tw.wiki.getTiddlerText("$:/config/HtmlParser/DisableSandbox","no") !== "yes") {
this.tree[0].attributes.sandbox = {type: "string", value: $tw.wiki.getTiddlerText("$:/config/HtmlParser/SandboxTokens","")};
}
};
exports["text/html"] = HtmlParser;

View File

@@ -39,6 +39,7 @@ exports["image/webp"] = ImageParser;
exports["image/heic"] = ImageParser;
exports["image/heif"] = ImageParser;
exports["image/x-icon"] = ImageParser;
exports["image/vnd.microsoft.icon"] = ImageParser;
})();

View File

@@ -123,6 +123,19 @@ exports.parseStringLiteral = function(source,pos) {
}
};
exports.parseMacroParameters = function(node,source,pos) {
// 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);
}
node.end = pos;
return node;
}
/*
Look for a macro invocation parameter. Returns null if not found, or {type: "macro-parameter", name:, value:, start:, end:}
*/
@@ -132,7 +145,7 @@ exports.parseMacroParameter = function(source,pos) {
start: pos
};
// Define our regexp
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^\s>"'=]+)))/g;
var reMacroParameter = /(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"""([\s\S]*?)"""|"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|((?:(?:>(?!>))|[^\s>"'])+)))/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for the parameter
@@ -187,14 +200,8 @@ exports.parseMacroInvocation = function(source,pos) {
}
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);
}
node = $tw.utils.parseMacroParameters(node,source,pos);
pos = node.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a double greater than sign
@@ -208,6 +215,29 @@ exports.parseMacroInvocation = function(source,pos) {
return node;
};
exports.parseFilterVariable = function(source) {
var node = {
name: "",
params: [],
},
pos = 0,
reName = /([^\s"']+)/g;
// If there is no whitespace or it is an empty string then there are no macro parameters
if(/^\S*$/.test(source)) {
node.name = source;
return node;
}
// Get the variable name
var nameMatch = $tw.utils.parseTokenRegExp(source,pos,reName);
if(nameMatch) {
node.name = nameMatch.match[1];
pos = nameMatch.end;
node = $tw.utils.parseMacroParameters(node,source,pos);
delete node.end;
}
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:,}
*/

View File

@@ -7,6 +7,12 @@ Wiki text block rule for HTML comments. For example:
```
<!-- This is a comment -->
\define macroX()
<!-- This is a comment -->
xxxx
\end
<!-- This is a comment -->
```
Note that the syntax for comments is simplified to an opening "<!--" sequence and a closing "-->" sequence -- HTML itself implements a more complex format (see http://ostermiller.org/findhtmlcomment.html)
@@ -19,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "<!--" sequence an
"use strict";
exports.name = "commentblock";
exports.types = {block: true};
exports.types = {block:true, pragma:true};
exports.init = function(parser) {
this.parser = parser;
@@ -31,7 +37,7 @@ exports.findNextMatch = function(startPos) {
this.matchRegExp.lastIndex = startPos;
this.match = this.matchRegExp.exec(this.parser.source);
if(this.match) {
this.endMatchRegExp.lastIndex = startPos + this.match[0].length;
this.endMatchRegExp.lastIndex = this.match.index + this.match[0].length;
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
if(this.endMatch) {
return this.match.index;

View File

@@ -31,7 +31,7 @@ exports.findNextMatch = function(startPos) {
this.matchRegExp.lastIndex = startPos;
this.match = this.matchRegExp.exec(this.parser.source);
if(this.match) {
this.endMatchRegExp.lastIndex = startPos + this.match[0].length;
this.endMatchRegExp.lastIndex = this.match.index + this.match[0].length;
this.endMatch = this.endMatchRegExp.exec(this.parser.source);
if(this.endMatch) {
return this.match.index;

View File

@@ -53,17 +53,12 @@ exports.parse = function() {
tag.isBlock = this.is.block || hasLineBreak;
// Parse the body if we need to
if(!tag.isSelfClosing && $tw.config.htmlVoidElements.indexOf(tag.tag) === -1) {
var reEndString = "</" + $tw.utils.escapeRegExp(tag.tag) + ">",
reEnd = new RegExp("(" + reEndString + ")","mg");
var reEndString = "</" + $tw.utils.escapeRegExp(tag.tag) + ">";
if(hasLineBreak) {
tag.children = this.parser.parseBlocks(reEndString);
} else {
tag.children = this.parser.parseInlineRun(reEnd);
}
reEnd.lastIndex = this.parser.pos;
var endMatch = reEnd.exec(this.parser.source);
if(endMatch && endMatch.index === this.parser.pos) {
this.parser.pos = endMatch.index + endMatch[0].length;
var reEnd = new RegExp("(" + reEndString + ")","mg");
tag.children = this.parser.parseInlineRun(reEnd,{eatTerminator: true});
}
}
// Return the tag

View File

@@ -36,7 +36,7 @@ exports.parse = function() {
// Move past the pragma invocation
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the filter terminated by a line break
var reMatch = /(.*)(\r?\n)|$/mg;
var reMatch = /(.*)(?:$|\r?\n)/mg;
reMatch.lastIndex = this.parser.pos;
var match = reMatch.exec(this.parser.source);
this.parser.pos = reMatch.lastIndex;

View File

@@ -21,40 +21,36 @@ exports.types = {block: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*?)>>(?:\r?\n|$)/mg;
};
exports.findNextMatch = function(startPos) {
var nextStart = startPos;
// Try parsing at all possible macrocall openers until we match
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
var nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
if(nextCall) {
var c = this.parser.source.charAt(nextCall.end);
// Ensure EOL after parsed macro
// If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym
if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) {
this.nextCall = nextCall;
return nextStart;
}
}
nextStart += 2;
}
return undefined;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Get all the details of the match
var macroName = this.match[1],
paramString = this.match[2];
// Move past the macro call
this.parser.pos = this.matchRegExp.lastIndex;
var params = [],
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] || paramMatch[6]
};
if(paramMatch[1]) {
paramInfo.name = paramMatch[1];
}
params.push(paramInfo);
// Find the next match
paramMatch = reParam.exec(paramString);
}
return [{
type: "macrocall",
name: macroName,
params: params,
isBlock: true
}];
var call = this.nextCall;
call.isBlock = true;
this.nextCall = null;
this.parser.pos = call.end;
return [call];
};
})();

View File

@@ -21,39 +21,29 @@ exports.types = {inline: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /<<([^\s>]+)\s*([\s\S]*?)>>/mg;
};
exports.findNextMatch = function(startPos) {
var nextStart = startPos;
// Try parsing at all possible macrocall openers until we match
while((nextStart = this.parser.source.indexOf("<<",nextStart)) >= 0) {
this.nextCall = $tw.utils.parseMacroInvocation(this.parser.source,nextStart);
if(this.nextCall) {
return nextStart;
}
nextStart += 2;
}
return undefined;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Get all the details of the match
var macroName = this.match[1],
paramString = this.match[2];
// Move past the macro call
this.parser.pos = this.matchRegExp.lastIndex;
var params = [],
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]|| paramMatch[6]
};
if(paramMatch[1]) {
paramInfo.name = paramMatch[1];
}
params.push(paramInfo);
// Find the next match
paramMatch = reParam.exec(paramString);
}
return [{
type: "macrocall",
name: macroName,
params: params
}];
var call = this.nextCall;
this.nextCall = null;
this.parser.pos = call.end;
return [call];
};
})();

View File

@@ -161,7 +161,7 @@ exports.parse = function() {
// Move the caption to the first row if it isn't already
if(table.children.length !== 1) {
table.children.pop(); // Take rowContainer out of the children array
table.children.splice(0,0,rowContainer); // Insert it at the bottom
table.children.splice(0,0,rowContainer); // Insert it at the bottom
}
// Set the alignment - TODO: figure out why TW did this
// rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";

View File

@@ -25,6 +25,14 @@ Attributes are stored as hashmaps of the following objects:
/*global $tw: false */
"use strict";
/*
type: content type of text
text: text to be parsed
options: see below:
parseAsInline: true to parse text as inline instead of block
wiki: reference to wiki to use
_canonical_uri: optional URI of content if text is missing or empty
*/
var WikiParser = function(type,text,options) {
this.wiki = options.wiki;
var self = this;
@@ -33,19 +41,6 @@ var WikiParser = function(type,text,options) {
this.loadRemoteTiddler(options._canonical_uri);
text = $tw.language.getRawString("LazyLoadingWarning");
}
// Initialise the classes if we don't have them already
if(!this.pragmaRuleClasses) {
WikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules("wikirule","pragma",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.pragmaRuleClasses,"$:/config/WikiParserRules/Pragmas/");
}
if(!this.blockRuleClasses) {
WikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules("wikirule","block",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.blockRuleClasses,"$:/config/WikiParserRules/Block/");
}
if(!this.inlineRuleClasses) {
WikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules("wikirule","inline",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.inlineRuleClasses,"$:/config/WikiParserRules/Inline/");
}
// Save the parse text
this.type = type || "text/vnd.tiddlywiki";
this.source = text || "";
@@ -54,13 +49,38 @@ var WikiParser = function(type,text,options) {
this.configTrimWhiteSpace = false;
// Set current parse position
this.pos = 0;
// Instantiate the pragma parse rules
this.pragmaRules = this.instantiateRules(this.pragmaRuleClasses,"pragma",0);
// Instantiate the parser block and inline rules
this.blockRules = this.instantiateRules(this.blockRuleClasses,"block",0);
this.inlineRules = this.instantiateRules(this.inlineRuleClasses,"inline",0);
// Parse any pragmas
// Start with empty output
this.tree = [];
// Assemble the rule classes we're going to use
var pragmaRuleClasses, blockRuleClasses, inlineRuleClasses;
if(options.rules) {
pragmaRuleClasses = options.rules.pragma;
blockRuleClasses = options.rules.block;
inlineRuleClasses = options.rules.inline;
} else {
// Setup the rule classes if we don't have them already
if(!this.pragmaRuleClasses) {
WikiParser.prototype.pragmaRuleClasses = $tw.modules.createClassesFromModules("wikirule","pragma",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.pragmaRuleClasses,"$:/config/WikiParserRules/Pragmas/");
}
pragmaRuleClasses = this.pragmaRuleClasses;
if(!this.blockRuleClasses) {
WikiParser.prototype.blockRuleClasses = $tw.modules.createClassesFromModules("wikirule","block",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.blockRuleClasses,"$:/config/WikiParserRules/Block/");
}
blockRuleClasses = this.blockRuleClasses;
if(!this.inlineRuleClasses) {
WikiParser.prototype.inlineRuleClasses = $tw.modules.createClassesFromModules("wikirule","inline",$tw.WikiRuleBase);
this.setupRules(WikiParser.prototype.inlineRuleClasses,"$:/config/WikiParserRules/Inline/");
}
inlineRuleClasses = this.inlineRuleClasses;
}
// Instantiate the pragma parse rules
this.pragmaRules = this.instantiateRules(pragmaRuleClasses,"pragma",0);
// Instantiate the parser block and inline rules
this.blockRules = this.instantiateRules(blockRuleClasses,"block",0);
this.inlineRules = this.instantiateRules(inlineRuleClasses,"inline",0);
// Parse any pragmas
var topBranch = this.parsePragmas();
// Parse the text into inline runs or blocks
if(options.parseAsInline) {
@@ -358,7 +378,7 @@ WikiParser.prototype.pushTextWidget = function(array,text) {
text = $tw.utils.trim(text);
}
if(text) {
array.push({type: "text", text: text});
array.push({type: "text", text: text});
}
};

View File

@@ -0,0 +1,181 @@
/*\
title: $:/core/modules/publisherhandler.js
type: application/javascript
module-type: global
The publisher manages publishing extracts of wikis as external files
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var PUBLISHING_MODAL_TITLE = "$:/language/Publishing/Modal";
/*
Instantiate the publisher manager with the following options
wiki: wiki object to be used
commander: commander object to be used for output
*/
function PublisherHandler(options) {
this.wiki = options.wiki;
this.commander = options.commander;
}
/*
Publish a job
jobTitle: title of tiddler containing details of the job
callback: completion callback invoked callback(err)
options: Include:
commander: commander object associated with publishing under Node.js
variables: hashmap of variables to be passed to renderings
*/
PublisherHandler.prototype.publish = function(jobTitle,callback,options) {
if(jobTitle) {
var job = new PublishingJob(jobTitle,this,options);
job.publish(callback);
}
};
function PublishingJob(jobTitle,publisherHandler,options) {
options = options || {};
// Save params
this.jobTitle = jobTitle;
this.publisherHandler = publisherHandler;
this.commander = options.commander;
this.publishVariables = options.variables || Object.create(null);
}
/*
Start publishing
*/
PublishingJob.prototype.publish = function(callback) {
var self = this;
// Get the job tiddler and check it is enabled
this.jobTiddler = this.publisherHandler.wiki.getTiddler(this.jobTitle);
if(this.jobTiddler && this.jobTiddler.fields.enabled === "yes") {
// Get the list of tiddlers to be exported, defaulting to all non-system tiddlers
this.exportList = this.publisherHandler.wiki.filterTiddlers(this.jobTiddler.fields["export-filter"] || "[!is[system]]");
// Get publisher
this.publisher = this.getPublisher(this.jobTiddler.fields.publisher);
if(this.publisher) {
// Get the sitemap
this.sitemap = new $tw.Sitemap(this.jobTiddler.fields.sitemap,{
wiki: this.publisherHandler.wiki,
variables: this.publishVariables
});
this.sitemap.load();
// Get the output operations
this.operations = this.sitemap.getAllFileDetails(this.exportList);
// Display the progress modal
if($tw.modal) {
this.progressModal = $tw.modal.display(PUBLISHING_MODAL_TITLE,{
progress: true,
variables: {
currentTiddler: this.jobTitle,
totalFiles: this.operations.length + ""
},
onclose: function(event) {
if(event !== self) {
// The modal was closed other than by us programmatically
self.isCancelled = true;
}
}
});
}
// Send the operations to the publisher
this.executeOperations(function(err) {
if(self.progressModal) {
self.progressModal.closeHandler(self);
}
callback(err);
});
} else {
return callback("Unrecognised publisher");
}
} else {
return callback("Missing or disabled job tiddler");
}
};
/*
Instantiate the required publisher object
*/
PublishingJob.prototype.getPublisher = function(publisherName) {
var publisher;
$tw.modules.forEachModuleOfType("publisher",function(title,module) {
if(module.name === publisherName) {
publisher = module;
}
});
return publisher && publisher.create(this.jobTiddler.fields,this.publisherHandler,this);
};
/*
Execute the operations for this job
*/
PublishingJob.prototype.executeOperations = function(callback) {
var self = this,
report = {overwrites: []},
nextOperation = 0,
performNextOperation = function() {
// Check for having been cancelled
if(self.isCancelled) {
if(self.publisher.publishCancel) {
self.publisher.publishCancel();
}
return callback("CANCELLED");
}
// Update progress
if(self.progressModal) {
self.progressModal.setProgress(nextOperation,self.operations.length);
}
// Check for having finished
if(nextOperation >= self.operations.length) {
$tw.utils.nextTick(function() {
self.publisher.publishEnd(callback);
});
} else {
// Execute this operation
var fileDetails = self.operations[nextOperation]();
nextOperation += 1;
self.publisher.publishFile(fileDetails,function() {
$tw.utils.nextTick(performNextOperation);
});
}
};
// Tell the publisher to start, and get back an array of the existing paths
self.publisher.publishStart(function(existingPaths) {
var paths = {};
$tw.utils.each(self.operations,function(operation) {
if(operation.path in paths) {
report.overwrites.push(operation.path);
}
paths[operation.path] = true;
});
// Run the operations
performNextOperation();
});
};
PublishingJob.prototype.saveReport = function(report) {
// Create the report tiddler
var reportTitle = this.wiki.generateNewTitle("$:/temp/publish-report");
$tw.wiki.addTiddler({
title: reportTitle,
text: "* " + report.overwrites.join("\n* ")
});
// Add the report tiddler title to the list field of the publisher parameters tiddler
var paramsTiddler = $tw.wiki.getTiddler(this.publisherParamsTitle),
list = (paramsTiddler.fields.list || []).slice(0);
list.unshift(reportTitle);
$tw.wiki.addTiddler(new $tw.Tiddler(paramsTiddler,{list: list}));
};
exports.PublisherHandler = PublisherHandler;
})();

View File

@@ -0,0 +1,52 @@
/*\
title: $:/core/modules/publishers/filesystem.js
type: application/javascript
module-type: publisher
Handles publishing to the Node.js filesystem
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "filesystem";
exports.create = function(params,publisherHandler,publishingJob) {
return new FileSystemPublisher(params,publisherHandler,publishingJob);
};
function FileSystemPublisher(params,publisherHandler,publishingJob) {
this.params = params;
this.publisherHandler = publisherHandler;
this.publishingJob = publishingJob;
};
FileSystemPublisher.prototype.publishStart = function(callback) {
console.log("publishStart");
// Returns a list of the previously published files
callback([]);
};
FileSystemPublisher.prototype.publishFile = function(item,callback) {
var fs = require("fs"),
path = require("path"),
filepath = path.resolve(this.publishingJob.commander.outputPath,item.path);
$tw.utils.createFileDirectories(filepath);
fs.writeFile(filepath,item.text,item.isBase64 ? "base64" : "utf8",function(err) {
if(err) {
console.log("File writing error",err)
}
callback(err);
});
};
FileSystemPublisher.prototype.publishEnd = function(callback) {
console.log("publishEnd");
callback(null);
};
})();

View File

@@ -157,7 +157,8 @@ SaverHandler.prototype.saveWiki = function(options) {
return false;
}
var variables = options.variables || {},
template = options.template || "$:/core/save/all",
template = (options.template ||
this.wiki.getTiddlerText("$:/config/SaveWikiButton/Template","$:/core/save/all")).trim(),
downloadType = options.downloadType || "text/plain",
text = this.wiki.renderTiddler(downloadType,template,options),
callback = function(err) {

View File

@@ -89,9 +89,12 @@ PutSaver.prototype.save = function(text,method,callback) {
if(err) {
// response is textual: "XMLHttpRequest error code: 412"
var status = Number(err.substring(err.indexOf(':') + 2, err.length))
if(status === 412) { // edit conflict
var message = $tw.language.getString("Error/EditConflict");
callback(message);
if(status === 412) { // file changed on server
callback($tw.language.getString("Error/PutEditConflict"));
} else if(status === 401) { // authentication required
callback($tw.language.getString("Error/PutUnauthorized"));
} else if(status === 403) { // permission denied
callback($tw.language.getString("Error/PutForbidden"));
} else {
callback(err); // fail
}

View File

@@ -28,17 +28,29 @@ UploadSaver.prototype.save = function(text,method,callback) {
password = $tw.utils.getPassword("upload"),
uploadDir = this.wiki.getTextReference("$:/UploadDir") || ".",
uploadFilename = this.wiki.getTextReference("$:/UploadFilename") || "index.html",
uploadWithUrlOnly = this.wiki.getTextReference("$:/UploadWithUrlOnly") || "no",
url = this.wiki.getTextReference("$:/UploadURL");
// Bail out if we don't have the bits we need
if(!username || username.toString().trim() === "" || !password || password.toString().trim() === "") {
return false;
if (uploadWithUrlOnly === "yes") {
// The url is good enough. No need for a username and password.
// Assume the server uses some other kind of auth mechanism.
if(!url || url.toString().trim() === "") {
return false;
}
}
else {
// Require username and password to be present.
// Assume the server uses the standard UploadPlugin username/password.
if(!username || username.toString().trim() === "" || !password || password.toString().trim() === "") {
return false;
}
}
// Construct the url if not provided
if(!url) {
url = "http://" + username + ".tiddlyspot.com/store.cgi";
}
// Assemble the header
var boundary = "---------------------------" + "AaB03x";
var boundary = "---------------------------" + "AaB03x";
var uploadFormName = "UploadPlugin";
var head = [];
head.push("--" + boundary + "\r\nContent-disposition: form-data; name=\"UploadPlugin\"\r\n");

View File

@@ -17,9 +17,8 @@ exports.method = "GET";
exports.path = /^\/favicon.ico$/;
exports.handler = function(request,response,state) {
response.writeHead(200, {"Content-Type": "image/x-icon"});
var buffer = state.wiki.getTiddlerText("$:/favicon.ico","");
response.end(buffer,"base64");
state.sendResponse(200,{"Content-Type": "image/x-icon"},buffer,"base64");
};
}());

View File

@@ -34,10 +34,7 @@ exports.handler = function(request,response,state) {
content = content;
type = ($tw.config.fileExtensionInfo[extension] ? $tw.config.fileExtensionInfo[extension].type : "application/octet-stream");
}
response.writeHead(status,{
"Content-Type": type
});
response.end(content);
state.sendResponse(status,{"Content-Type": type},content);
});
};

View File

@@ -12,38 +12,16 @@ GET /
/*global $tw: false */
"use strict";
var zlib = require("zlib");
exports.method = "GET";
exports.path = /^\/$/;
exports.path = /^\/index.html$/;
exports.handler = function(request,response,state) {
var acceptEncoding = request.headers["accept-encoding"];
if(!acceptEncoding) {
acceptEncoding = "";
}
var text = state.wiki.renderTiddler(state.server.get("root-render-type"),state.server.get("root-tiddler")),
responseHeaders = {
"Content-Type": state.server.get("root-serve-type")
};
/*
If the gzip=yes flag for `listen` is set, check if the user agent permits
compression. If so, compress our response. Note that we use the synchronous
functions from zlib to stay in the imperative style. The current `Server`
doesn't depend on this, and we may just as well use the async versions.
*/
if(state.server.enableGzip) {
if (/\bdeflate\b/.test(acceptEncoding)) {
responseHeaders["Content-Encoding"] = "deflate";
text = zlib.deflateSync(text);
} else if (/\bgzip\b/.test(acceptEncoding)) {
responseHeaders["Content-Encoding"] = "gzip";
text = zlib.gzipSync(text);
}
}
response.writeHead(200,responseHeaders);
response.end(text);
state.sendResponse(200,responseHeaders,text);
};
}());

View File

@@ -22,11 +22,12 @@ exports.handler = function(request,response,state) {
response.writeHead(401,{
"WWW-Authenticate": 'Basic realm="Please provide your username and password to login to ' + state.server.servername + '"'
});
response.end();
response.end();
} else {
// Redirect to the root wiki if login worked
var location = ($tw.syncadaptor && $tw.syncadaptor.host)? $tw.syncadaptor.host: "/";
response.writeHead(302,{
Location: "/"
Location: location
});
response.end();
}

View File

@@ -17,17 +17,17 @@ exports.method = "GET";
exports.path = /^\/status$/;
exports.handler = function(request,response,state) {
response.writeHead(200, {"Content-Type": "application/json"});
var text = JSON.stringify({
username: state.authenticatedUsername || state.server.get("anon-username") || "",
anonymous: !state.authenticatedUsername,
read_only: !state.server.isAuthorized("writers",state.authenticatedUsername),
sse_enabled: state.server.get("sse-enabled") === "yes",
space: {
recipe: "default"
},
tiddlywiki_version: $tw.version
});
response.end(text,"utf8");
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
};
}());

View File

@@ -32,9 +32,9 @@ exports.handler = function(request,response,state) {
renderTemplate = renderTemplate || state.server.get("tiddler-render-template");
}
var text = state.wiki.renderTiddler(renderType,renderTemplate,{parseAsInline: true, variables: {currentTiddler: title}});
// Naughty not to set a content-type, but it's the easiest way to ensure the browser will see HTML pages as HTML, and accept plain text tiddlers as CSS or JS
response.writeHead(200);
response.end(text,"utf8");
state.sendResponse(200,{},text,"utf8");
} else {
response.writeHead(404);
response.end();

View File

@@ -36,8 +36,7 @@ exports.handler = function(request,response,state) {
tiddlerFields.revision = state.wiki.getChangeCount(title);
tiddlerFields.bag = "default";
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
response.writeHead(200, {"Content-Type": "application/json"});
response.end(JSON.stringify(tiddlerFields),"utf8");
state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8");
} else {
response.writeHead(404);
response.end();

View File

@@ -33,7 +33,6 @@ exports.handler = function(request,response,state) {
}
var excludeFields = (state.queryParameters.exclude || "text").split(","),
titles = state.wiki.filterTiddlers(filter);
response.writeHead(200, {"Content-Type": "application/json"});
var tiddlers = [];
$tw.utils.each(titles,function(title) {
var tiddler = state.wiki.getTiddler(title);
@@ -45,7 +44,7 @@ exports.handler = function(request,response,state) {
}
});
var text = JSON.stringify(tiddlers);
response.end(text,"utf8");
state.sendResponse(200,{"Content-Type": "application/json"},text,"utf8");
};
}());

View File

@@ -0,0 +1,70 @@
/*\
title: $:/core/modules/server/server-sent-events.js
type: application/javascript
module-type: library
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
parameters:
prefix - usually the plugin path, such as `plugins/tiddlywiki/tiddlyweb`. The
route will match `/events/${prefix}` exactly.
handler - a function that will be called each time a request comes in with the
request and state from the route and an emit function to call.
*/
var ServerSentEvents = function ServerSentEvents(prefix, handler) {
this.handler = handler;
this.prefix = prefix;
};
ServerSentEvents.prototype.getExports = function() {
return {
bodyFormat: "stream",
method: "GET",
path: new RegExp("^/events/" + this.prefix + "$"),
handler: this.handleEventRequest.bind(this)
};
};
ServerSentEvents.prototype.handleEventRequest = function(request,response,state) {
if(ServerSentEvents.prototype.isEventStreamRequest(request)) {
response.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
this.handler(request,state,this.emit.bind(this,response),this.end.bind(this,response));
} else {
response.writeHead(406,"Not Acceptable",{});
response.end();
}
};
ServerSentEvents.prototype.isEventStreamRequest = function(request) {
return request.headers.accept &&
request.headers.accept.match(/^text\/event-stream/);
};
ServerSentEvents.prototype.emit = function(response,event,data) {
if(typeof event !== "string" || event.indexOf("\n") !== -1) {
throw new Error("Type must be a single-line string");
}
if(typeof data !== "string" || data.indexOf("\n") !== -1) {
throw new Error("Data must be a single-line string");
}
response.write("event: " + event + "\ndata: " + data + "\n\n", "utf8");
};
ServerSentEvents.prototype.end = function(response) {
response.end();
};
exports.ServerSentEvents = ServerSentEvents;
})();

View File

@@ -17,7 +17,9 @@ if($tw.node) {
fs = require("fs"),
url = require("url"),
path = require("path"),
querystring = require("querystring");
querystring = require("querystring"),
crypto = require("crypto"),
zlib = require("zlib");
}
/*
@@ -40,13 +42,15 @@ function Server(options) {
if(options.variables[variable]) {
this.variables[variable] = options.variables[variable];
}
}
}
}
$tw.utils.extend({},this.defaultVariables,options.variables);
// Initialise CSRF
this.csrfDisable = this.get("csrf-disable") === "yes";
// Initialize Gzip compression
this.enableGzip = this.get("gzip") === "yes";
// Initialize browser-caching
this.enableBrowserCache = this.get("use-browser-cache") === "yes";
// Initialise authorization
var authorizedUserName = (this.get("username") && this.get("password")) ? this.get("username") : "(anon)";
this.authorizationPrincipals = {
@@ -59,10 +63,7 @@ function Server(options) {
self.addAuthenticator(authenticatorDefinition.AuthenticatorClass);
});
// Load route handlers
$tw.modules.forEachModuleOfType("route", function(title,routeDefinition) {
// console.log("Loading server route " + title);
self.addRoute(routeDefinition);
});
this.addRouteHandlers();
// Initialise the http vs https
this.listenOptions = null;
this.protocol = "http";
@@ -78,6 +79,71 @@ function Server(options) {
this.transport = require(this.protocol);
}
/*
Send a response to the client. This method checks if the response must be sent
or if the client alrady has the data cached. If that's the case only a 304
response will be transmitted and the browser will use the cached data.
Only requests with status code 200 are considdered for caching.
request: request instance passed to the handler
response: response instance passed to the handler
statusCode: stauts code to send to the browser
headers: response headers (they will be augmented with an `Etag` header)
data: the data to send (passed to the end method of the response instance)
encoding: the encoding of the data to send (passed to the end method of the response instance)
*/
function sendResponse(request,response,statusCode,headers,data,encoding) {
if(this.enableBrowserCache && (statusCode == 200)) {
var hash = crypto.createHash('md5');
// Put everything into the hash that could change and invalidate the data that
// the browser already stored. The headers the data and the encoding.
hash.update(data);
hash.update(JSON.stringify(headers));
if(encoding) {
hash.update(encoding);
}
var contentDigest = hash.digest("hex");
// RFC 7232 section 2.3 mandates for the etag to be enclosed in quotes
headers["Etag"] = '"' + contentDigest + '"';
headers["Cache-Control"] = "max-age=0, must-revalidate";
// Check if any of the hashes contained within the if-none-match header
// matches the current hash.
// If one matches, do not send the data but tell the browser to use the
// cached data.
// We do not implement "*" as it makes no sense here.
var ifNoneMatch = request.headers["if-none-match"];
if(ifNoneMatch) {
var matchParts = ifNoneMatch.split(",").map(function(etag) {
return etag.replace(/^[ "]+|[ "]+$/g, "");
});
if(matchParts.indexOf(contentDigest) != -1) {
response.writeHead(304,headers);
response.end();
return;
}
}
}
/*
If the gzip=yes is set, check if the user agent permits compression. If so,
compress our response if the raw data is bigger than 2k. Compressing less
data is inefficient. Note that we use the synchronous functions from zlib
to stay in the imperative style. The current `Server` doesn't depend on
this, and we may just as well use the async versions.
*/
if(this.enableGzip && (data.length > 2048)) {
var acceptEncoding = request.headers["accept-encoding"] || "";
if(/\bdeflate\b/.test(acceptEncoding)) {
headers["Content-Encoding"] = "deflate";
data = zlib.deflateSync(data);
} else if(/\bgzip\b/.test(acceptEncoding)) {
headers["Content-Encoding"] = "gzip";
data = zlib.gzipSync(data);
}
}
response.writeHead(statusCode,headers);
response.end(data,encoding);
}
Server.prototype.defaultVariables = {
port: "8080",
host: "127.0.0.1",
@@ -89,7 +155,8 @@ Server.prototype.defaultVariables = {
"system-tiddler-render-type": "text/plain",
"system-tiddler-render-template": "$:/core/templates/wikified-tiddler",
"debug-level": "none",
"gzip": "no"
"gzip": "no",
"use-browser-cache": "no"
};
Server.prototype.get = function(name) {
@@ -112,11 +179,43 @@ Server.prototype.addAuthenticator = function(AuthenticatorClass) {
}
};
Server.prototype.findMatchingRoute = function(request,state) {
Server.prototype.addRouteHandlers = function() {
var self = this;
// Load route handlers from sitemap if present, or just load all route modules
if(this.variables.sitemap) {
this.sitemap = new $tw.Sitemap(this.variables.sitemap,{
wiki: this.wiki,
variables: {}
});
this.sitemap.load();
$tw.utils.each(this.sitemap.getServerRoutes(),function(routeInfo) {
self.addRoute({
method: "GET",
path: routeInfo.regexp,
handler: function(request,response,state) {
var fileDetails = routeInfo.handler(state.params);
if(fileDetails) {
response.writeHead(200, {"Content-Type": fileDetails.type});
response.end(fileDetails.text,fileDetails.isBase64 ? "base64" : "utf8");
} else {
response.writeHead(404);
response.end();
}
}
});
});
} else {
$tw.modules.forEachModuleOfType("route",function(title,routeDefinition) {
self.addRoute(routeDefinition);
});
}
};
Server.prototype.findMatchingRoute = function(request,state,options) {
options = options || {};
for(var t=0; t<this.routes.length; t++) {
var potentialRoute = this.routes[t],
pathRegExp = potentialRoute.path,
pathname = state.urlInfo.pathname,
pathname = options.pathname || state.urlInfo.pathname,
match;
if(state.pathPrefix) {
if(pathname.substr(0,state.pathPrefix.length) === state.pathPrefix) {
@@ -167,13 +266,14 @@ Server.prototype.requestHandler = function(request,response,options) {
state.urlInfo = url.parse(request.url);
state.queryParameters = querystring.parse(state.urlInfo.query);
state.pathPrefix = options.pathPrefix || this.get("path-prefix") || "";
state.sendResponse = sendResponse.bind(self,request,response);
// Get the principals authorized to access this resource
var authorizationType = this.methodMappings[request.method] || "readers";
// Check for the CSRF header if this is a write
if(!this.csrfDisable && authorizationType === "writers" && request.headers["x-requested-with"] !== "TiddlyWiki") {
response.writeHead(403,"'X-Requested-With' header required to login to '" + this.servername + "'");
response.end();
return;
return;
}
// Check whether anonymous access is granted
state.allowAnon = this.isAuthorized(authorizationType,null);
@@ -182,7 +282,7 @@ Server.prototype.requestHandler = function(request,response,options) {
if(!this.authenticators[0].authenticateRequest(request,response,state)) {
// Bail if we failed (the authenticator will have sent the response)
return;
}
}
}
// Authorize with the authenticated username
if(!this.isAuthorized(authorizationType,state.authenticatedUsername)) {
@@ -192,6 +292,15 @@ Server.prototype.requestHandler = function(request,response,options) {
}
// Find the route that matches this path
var route = self.findMatchingRoute(request,state);
if(!route) {
// Try with the default document
var defaultDocumentPathname = state.urlInfo.pathname;
if(defaultDocumentPathname.substr(-1) !== "/") {
defaultDocumentPathname = defaultDocumentPathname + "/";
}
defaultDocumentPathname = defaultDocumentPathname + "index.html";
route = self.findMatchingRoute(request,state,{pathname: defaultDocumentPathname});
}
// Optionally output debug info
if(self.get("debug-level") !== "none") {
console.log("Request path:",JSON.stringify(state.urlInfo));

236
core/modules/sitemap.js Normal file
View File

@@ -0,0 +1,236 @@
/*\
title: $:/core/modules/sitemap.js
type: application/javascript
module-type: global
Sitemaps are used for static publishing and web serving
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function Sitemap(sitemapTitle,options) {
options = options || {};
this.sitemapTitle = sitemapTitle;
this.wiki = options.wiki;
this.routes = [];
this.variables = $tw.utils.extend({},options.variables);
}
Sitemap.prototype.load = function(sitemapTitle) {
var self = this;
// Get the sitemap
var sitemapTiddler = this.wiki.getTiddler(this.sitemapTitle);
if(sitemapTiddler) {
// Collect each route
$tw.utils.each(sitemapTiddler.fields.list,function(routeTitle) {
var routeTiddler = self.wiki.getTiddler(routeTitle);
if(routeTiddler) {
// Convert the path into a regexp and an array of {field:,function:} for each capture group
var regexpurgatedParameterisedPath = self.regexpurgateParameterisedPath(routeTiddler.fields["route-path"]);
self.routes.push({
title: routeTitle,
params: routeTiddler.getFieldStrings({prefix: "route-"}),
variables: routeTiddler.getFieldStrings({prefix: "var-"}),
regexp: regexpurgatedParameterisedPath.regexp,
captureGroups: regexpurgatedParameterisedPath.captureGroups
});
}
});
}
};
Sitemap.prototype.renderRoute = function(title,route) {
var tiddler = this.wiki.getTiddler(title);
switch(route.params.type) {
case "raw":
return {
path: this.resolveParameterisedPath(route.params.path,title),
text: tiddler.fields.text || "",
type: tiddler.fields.type || "",
isBase64: ($tw.config.contentTypeInfo[tiddler.fields.type] || {}).encoding === "base64"
};
break;
case "render":
var parser = {
tree: [
{
"type": "importvariables",
"attributes": {
"tiddler": {
"name": "tiddler",
"type": "string",
"value": this.sitemapTitle,
}
},
"tag": "$importvariables",
"isBlock": false,
"children": [
{
"type": "importvariables",
"attributes": {
"tiddler": {
"name": "tiddler",
"type": "string",
"value": route.title,
}
},
"tag": "$importvariables",
"isBlock": false,
"children": this.wiki.parseTiddler(route.params.template,{parseAsInline: true}).tree
}
]
}
]
},
widgetNode = this.wiki.makeWidget(parser,{
variables: $tw.utils.extend({},this.variables,{currentTiddler: title})
}),
container = $tw.fakeDocument.createElement("div");
widgetNode.render(container,null);
return {
path: this.resolveParameterisedPath(route.params.path,title),
text: container.textContent,
type: route.params["output-type"] || "text/html"
};
break;
}
};
/*
Returns an array of functions that return {path:,text:,type:,isBase64:} for each path
*/
Sitemap.prototype.getAllFileDetails = function(exportTiddlers) {
var self = this,
output = [];
$tw.utils.each(this.routes,function(route) {
var routeFilter = route.params["tiddler-filter"] || "DUMMY_RESULT", // If no filter is provided, use a dummy filter that returns a single result
routeTiddlers = self.wiki.filterTiddlers(routeFilter,null,self.wiki.makeTiddlerIterator(exportTiddlers));
$tw.utils.each(routeTiddlers,function(title) {
output.push(self.renderRoute.bind(self,title,route));
});
});
return output;
};
/*
Returns an array of server routes {regexp:, handler:}
*/
Sitemap.prototype.getServerRoutes = function() {
var self = this,
output = [];
$tw.utils.each(this.routes,function(route) {
output.push({
regexp: route.regexp,
handler: function(params) {
// Locate the tiddler identified by the capture groups, if any
var title = null,
nextParam = 0;
$tw.utils.each(route.captureGroups,function(captureGroup) {
var param = params[nextParam++];
if(captureGroup.field === "title") {
switch(captureGroup.function) {
case "slugify":
var titles = self.wiki.unslugify(param);
if(titles && titles.length > 0) {
title = titles[0];
}
break;
}
}
})
// Check that the tiddler passes the route filter
if(route.params["tiddler-filter"]) {
if(!title) {
return null;
}
var routeTiddlers = self.wiki.filterTiddlers(route.params["tiddler-filter"],null,self.wiki.makeTiddlerIterator([title]));
if(routeTiddlers.indexOf(title) === -1) {
return null;
}
}
// Return the rendering or raw tiddler
return self.renderRoute(title,route);
}
});
});
return output;
};
/*
Apply a tiddler to a parameterised path to create a usable path
*/
Sitemap.prototype.resolveParameterisedPath = function(parameterisedPath,title) {
var self = this;
// Split the path on $*_*$ markers
var tiddler = this.wiki.getTiddler(title),
output = [];
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
if(match) {
var value;
// Get the base value
switch(match[1]) {
case "uri":
case "title":
value = title;
break;
case "type":
value = tiddler.fields.type || "text/vnd.tiddlywiki";
break;
}
// Apply the encoding function
switch(match[2]) {
case "encoded":
value = encodeURIComponent(value);
break;
case "doubleencoded":
value = encodeURIComponent(encodeURIComponent(value));
break;
case "slugify":
value = self.wiki.slugify(value);
break;
case "extension":
value = ($tw.config.contentTypeInfo[value] || {extension: "."}).extension.slice(1);
break;
}
output.push(value);
} else {
output.push(part);
}
});
return output.join("");
};
/*
// Convert the path into a regexp and an array of {field:,function:} for each capture group
*/
Sitemap.prototype.regexpurgateParameterisedPath = function(parameterisedPath) {
var regexpParts = ["\\/"],
captureGroups = [];
$tw.utils.each(parameterisedPath.split(/(\$[a-z_]+\$)/),function(part) {
var match = part.match(/\$([a-z]+)_([a-z]+)\$/);
if(match) {
regexpParts.push("(.+)");
captureGroups.push({
field: match[1],
function: match[2]
});
} else {
regexpParts.push($tw.utils.escapeRegExp(part));
}
});
return {
regexp: new RegExp("^" + regexpParts.join("") + "$"),
captureGroups: captureGroups
};
};
exports.Sitemap = Sitemap;
})();

View File

@@ -17,7 +17,7 @@ exports.name = "favicon";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
// Favicon tiddler
var FAVICON_TITLE = "$:/favicon.ico";

View File

@@ -22,6 +22,9 @@ exports.startup = function() {
if($tw.node) {
$tw.modules.applyMethods("utils-node",$tw.utils);
}
if($tw.browser) {
$tw.modules.applyMethods("utils-browser",$tw.utils);
}
$tw.modules.applyMethods("global",$tw);
$tw.modules.applyMethods("config",$tw.config);
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");

View File

@@ -82,7 +82,7 @@ exports.startup = function() {
var onlyThrottledTiddlersHaveChanged = true;
for(var title in changes) {
var tiddler = $tw.wiki.getTiddler(title);
if(!tiddler || !(tiddler.hasField("draft.of") || tiddler.hasField("throttle.refresh"))) {
if(!$tw.wiki.isVolatileTiddler(title) && (!tiddler || !(tiddler.hasField("draft.of") || tiddler.hasField("throttle.refresh")))) {
onlyThrottledTiddlersHaveChanged = false;
}
}

View File

@@ -27,7 +27,7 @@ exports.startup = function() {
});
$tw.rootWidget.addEventListener("tm-show-switcher",function(event) {
$tw.modal.display("$:/core/ui/SwitcherModal",{variables: event.paramObject, event: event});
});
});
// Install the notification mechanism
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
$tw.rootWidget.addEventListener("tm-notify",function(event) {
@@ -40,9 +40,10 @@ exports.startup = function() {
// Install the tm-focus-selector message
$tw.rootWidget.addEventListener("tm-focus-selector",function(event) {
var selector = event.param || "",
element;
element,
doc = event.event && event.event.target ? event.event.target.ownerDocument : document;
try {
element = document.querySelector(selector);
element = doc.querySelector(selector);
} catch(e) {
console.log("Error in selector: ",selector)
}
@@ -68,10 +69,16 @@ exports.startup = function() {
fullScreenDocument[fullscreen._exitFullscreen]();
} else {
fullScreenDocument.documentElement[fullscreen._requestFullscreen](Element.ALLOW_KEYBOARD_INPUT);
}
}
}
});
}
// Hook up events for the publisher handler
$tw.rootWidget.addEventListener("tm-publish",function(event) {
$tw.publisherHandler.publish(event.paramObject.job,function(err) {
console.log("Finished publishing with result:",err);
});
});
// If we're being viewed on a data: URI then give instructions for how to save
if(document.location.protocol === "data:") {
$tw.rootWidget.dispatchEvent({

View File

@@ -23,7 +23,6 @@ var PERFORMANCE_INSTRUMENTATION_CONFIG_TITLE = "$:/config/Performance/Instrument
var widget = require("$:/core/modules/widgets/widget.js");
exports.startup = function() {
var modules,n,m,f;
// Minimal browser detection
if($tw.browser) {
$tw.browser.isIE = (/msie|trident/i.test(navigator.userAgent));
@@ -66,10 +65,10 @@ exports.startup = function() {
// Execute any startup actions
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction");
if($tw.browser) {
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Browser");
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Browser");
}
if($tw.node) {
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Node");
$tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Node");
}
// Kick off the language manager and switcher
$tw.language = new $tw.Language();
@@ -130,6 +129,10 @@ exports.startup = function() {
dirtyTracking: !$tw.syncadaptor,
preloadDirty: $tw.boot.preloadDirty || []
});
// Install the publisher handler
$tw.publisherHandler = new $tw.PublisherHandler({
wiki: $tw.wiki
});
// Host-specific startup
if($tw.browser) {
// Install the popup manager

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