This fixes a bug in #3634, and refines the logic so that the warning is only given if the incoming tiddler exists as a shadow tiddler. (In my case I have several draft core modules inactive in my notes wiki and they were erroneously suppressed from the upgrade).
* add "delayed" option to tm-focus-selector message
this delays the focussing for the time of the animation duration if delayed="yes" or delayed="true"
this is useful when navigating the story river up and down with keyboard shortcuts and the shortcuts focus the title input if a navigated tiddler is in edit mode -> navigation doesn't jump but stays smooth
* Update rootwidget.js
* Update WidgetMessage_ tm-focus-selector.tid
* add preventScroll="true" tip
* Transform GitHub saver to work with GitLab as well
You can choose which provider you want to use, the data is given in the
same place.
I tried to avoid code duplication, so service providers' unique
properties are in separate files, the settings of the selected provider
are loaded.
In two fields I am not sure that it fits into the current structure:
* module-type: gitservice
Which module is a `gitservice` type, it will be listed in the
drop-down menu.
* default-api-url: https://gitlab.com/api/v4
The default URL to access the provider's API.
This is just a sketch, not a final version, suggestions for modification
are welcome!
* Rename saver from GitHub to GitService, update docs
* Split GitHub and GitLab to separate savers, apply common lingo
Sadly, it doesn't seem to make much sense to search for common parts in
the code, because there might be a Git service that is very different
from the GitHub API (such as BitBucket). Therefore, I feel that Git
savers are not able to share other than the translations.
I deleted the defaults values from the translations and set it to the
text entry because they should not depend on the translations.
* Add more information about the password field
It is not clear how to create a personal access token, thus added a link
to the help pages. In addition, GitLab only accepts personal access
token, GitHub also accepts the password, so I made this clear.
* Extract commit message to lingo
* Fix indentation
* Use improved base64 encoder
Fix conflict with a06acc4eb8
Fixes#4082
This version removes selective updating of the tag index, instead completely clearing the index on each update. I'm investigating restoring that optimisation.
* Remove the th-renaming-tiddler hook from navigatior.js
The hook is invoked in the renameTiddler function which would cause the same hook to be called twice, and the version in the navigator widget didn't have the correct inputs and return value according to the documentation.
* Make it so that the th-renaming-tiddler hook isn't called twice
by removing it from the navigator.js file
The test rig previously used a simplified implementation of shadow tiddlers which broke with the new indexing engine. There was also a problem that made that even if indexers were disabled they were still initialised.
This PR fixes both problems, in preparation for fixing #4082
See discussion at https://groups.google.com/d/msgid/tiddlywiki/526754d5-8786-49cd-aaa1-c77311670116%40googlegroups.com:
The history here is that in v5.1.14 we added an "actions" attribute to the checkbox widget that specified an action string to be specified whenever the state of the checkbox changed. The same action string is executed regardless of whether the checkbox was checked or unchecked.
Then in v5.1.16 we merged https://github.com/Jermolene/TiddlyWiki5/pull/3182 which added the "uncheckactions" attribute. The difference between the two is that the uncheckactions are only executed if the checkbox is unchecked. The main "actions" attribute is executed before any actions in "uncheckactions", which makes it possible to arrange things so that the "actions" attribute sets things to the checked state while the "uncheckactions" attribute overwrites those changes to set things to the unchecked state.
In retrospect, it would have made more sense to have also added a "checkactions" attribute that was executed only if the checkbox was checked. I'll investigate adding it for v5.1.20.
Make good use of "$:/core/modules/utils/base64-utf8/base64-utf8.module.js"
* Add a new base64Encode()
* Both of base64Encode and base64Decode work for Nodejs and Browsers
This adds options.wiki to the object sent to the generateTiddlerFilePath
The function generateTiddlerFilePath can take a wiki in the options object, but generateTiddlerFileInfo doesn't pass the wiki to it.
* add escapecss filter
this filter would allow creating valid css classes from titles containing special characters
we assign a class to an element using `encodeuricomponent[]` so that the class name is encoded
in a stylesheet we create the classname by `<title>escapecss[]` which applies the uri encoding and escapes characters that need to be escaped
* Update encodings.js
* refactor tagToCssSelector, add escapeCssSelector
* use escapeCssSelector
* escape using CSS.escape if it's available
* Update encodings.js
* revert factoring out escapeCssSelector
... this makes the animation when inserting tiddlers / navigating to tiddlers in the pop storyview less jumpy
it simply sets `overflow-x` to `hidden` for the time of the insert-animation
* First pass at modular wiki indexes
An exploratory experiment
* Fix tests
* Faster checking for existence of index methods
We don't really need to check the type
* Use the index for the has operator
* Fix typo
* Move iterator index methods into indexer modules
Now boot.js doesn't know the core indexers
* Fix up the other iterator index functions
* Fix crash with missing index branch
* Limit the field indexer to values less than 128 characters
* Fallback to the old manual scan if the index method returns null
* Sadly, we can no longe re-use the field indexer to accelerate the `has` operator, because the index now omits tiddlers that have field values longer than the limit
Still need to make the index configuration exposed somehow
* Rearrange tests so that we can test with and without indexers
We also need to expose the list of enabled indexers as a config option
* Test the field indexer with different length fields
So that we test the indexed and non-indexed codepaths
It turns out that the `localeCompare` function used by `compareStateText()` is very, very slow. Replacing it with a straightforward equality test makes one of my test rigs be 10x faster...
Note that this PR reverts the behaviour of match/nomatch to that before #3157. That change was not backwards compatible in that the switch to localeCompare meant that é === e, now it doesn't again.
Approximtely 50% speed improvement in tests opening a storyview with 8,000 entries.
(I've deferred the indentation adjustments until the next commit so that the git diffs are clearer)
Fixes#3875
* Use .json files (instead of .tid) for any tiddler whose fields contain values that can't be stored as a .tid file
* Save application/json tiddlers as .json files
* Refactor most of the file handling as re-usable utilities
If the path was not specified, RSOD error occurred when we wanted to
download the wiki:
Uncaught TypeError: Cannot read property 'substring' of undefined
* Add uniquetitle macro
This macro is a wrapper on the $tw.wiki.generateNewTitle function to return a unique name, it has been requested multiple times in the forums.
* Add documentation tiddler for uniquetitle macro
* Add uniquetitle macro examples
* Change name from uniquetitle to unusedtitle for clarity
The title isn't unique, just not currently used in the wiki.
* Update uniquetitle to unusedtitle
* Change uniquetitle to unusedtitle
* Fix a typo
@BurningTreeC I think this might have been a typo in your recent refactorings; if you look back at an old version such as c0c1b557eb/core/modules/widgets/reveal.js then there is no sign of this fallback.
Fixes#3874
* add focus capability to edit-shortcut widget
* focus the keyboard-shortcut inputs in the control panel
... there's no other reason why it could have been opened other than just pressing a shorcut ...
... saves the mouseclick
in my tests listening for the dragend event and removing the tc-dragover class in that case removes the `tc-dragover` every time it should ...
without this, firefox often doesn't remove it and the green bar sticks at the top
investigating now if the droppable widget has a similar problem
There are other ways we could add maths to TW5 (including @EvanBalster's awesome https://github.com/EvanBalster/TiddlyWikiFormula) but the approach here has the merit of simplicity because it reuses the existing filter evaluation mechanism. That means that it's not ordinary "2+2" maths, it's a unique list processing language...
Docs to come
Fixes#254
As per the discussion in #3749, the original purpose of the removed condition is unknown, and so we cannot be certain that removing it is safe, but doing so seems the best way of discovering more...
* Fix search method for search tokens spread across fields
Addresses GH #3636, which reports that if you're searching for "test
body", and "test" only appears in the title field, and "body" only appears
in the text field, 5.1.18's search method won't yield that tiddler as a
result, which appears to be a regression from the 5.1.17 behavior
* Add test for searching for multiple tokens across fields
Verifies GH #3636:
> If I create a tiddler in the empty edition with the title "Test tiddler" and content "Body content", searching the wiki for "test body" yields no results under either "title matches" or "all matches". Searching for either word individually turns up "Test tiddler", and repeating this in an empty wiki I created from the 5.1.17 tag causes "Test tiddler" to show up under "all matches".
* Revert "v5.1.18 banner artwork"
This reverts commit 70500140b9.
* Revert "Revert #3607 and #3608"
This reverts commit 87b3e470c2.
* Revert "Fix default global keyboard shortcuts for Mac"
This reverts commit e466f62e7e.
* Revert "Comment plugin: Improve styles"
This reverts commit e17456e3bc.
* Revert "Style tweaks for framed editor + preview (#3608)"
This reverts commit c058378da0.
* Revert "Change to natural counting in range[N] operator (#3609)"
This reverts commit b9df224f99.
* Revert "Update release note contributors list"
This reverts commit 0f3912ba95.
* Revert "Make editor-preview not hide text-editor shadow (#3607)"
This reverts commit 11f02dc362.
* Revert "Editor needs to stand out a bit more (#3606)"
This reverts commit d711ef25ed.
* Revert "Tweak for keyboard-shortcuts how-to (#3605)"
This reverts commit 419ea9a243.
* Revert "Remove unnecessary border-radius already set on the iframe (#3604)"
This reverts commit 288d25e733.
Hi @BurningTreeC apologies I merged these without properly looking at them, but I think we should move them to 5.1.19 because:
* On Chrome, the new version hides the resize handle on textarea, which can be quite useful
* It's visually quite different, and I think might benefit from more discussion
* It's inconsistent with the CodeMirror editor
Would you mind perhaps starting another PR for edit template enhancements?
* remove border: none for iframe from framed.js
... inherits the iframe border 1px solid editor-border in vanilla base
* last style tweaks for editor-preview
same border-radius as framed editor
same additional space at the right as at the left
* Update base.tid
* Update base.tid
* looks actually better with this border
Addresses GH #3484
As far as I can tell, the popup level checks in this module are
meant to handle nested popups. It seems to me that the goal is
for at most a single hierarchy of popups to exist at any given time
- bearing that in mind, this change checks any popups currently tracked
by the module, canceling any that don't share an element hierarchy with
the new popup.
* add tv-override-missing-links variable
this lets us set `tv-override-missing-links` true so that we can fix edge cases like the `Filter` dropdown in the `Advanced Search` when `enable missing links` is unchecked in the `Settings` tab of the Control Panel
* add tv-override-missing-links to filter dropdown
* add tv-override-missing-links to type dropdown
* add tv-override-missing-links to fieldname dropd
* add tv-override-missing-links to TagManager(icons)
* undo tv-override-missing-links TagManager
not needed here
* Update link.js
* Update dropdown.tid
* Update fields.tid
* Update type.tid
* Update dropdown.tid
* Update link.js
* simplify all together
* add tv-hide-missing-links to pagetemplate
* do we need to refresh here...
... if the variable gets set on top of the pagetemplate?
* Make modals display in source Window
this makes modals display within the window where they got opened, with the parameter `rootwindow` that, if `yes` or `true`, shows the modal always in the root TW window (`<$action-sendmessage $message="tm-modal" $param="mymodal" rootwindow="yes|true"/>`)
* pass the full event to $tw.modal.display
we need the event there to find `srcDocument` and `srcWindow`
* pass event in options object
* update modal.js to use options.event
* add docs for rootwindow tm-modal attribute
* make triggerPopup optionally set state directly
* update button widget for new state attributes
* update reveal widget for new state attributes
* fix errors in button widget
this makes a keyboard widget update its keyInfoArray if its key has the `((descriptor))` format and one of the platform-specific configuration tiddlers with that descriptor-suffix changes
this allows using the pagescroller for scrolling elements into view where the rect gets calculated somewhere else
Example: CodeMirror has the `cm.cursorCoords()` function that returns the rect of the textselection (or cursor coordinates)
this scrolls the cursor or text selection into view using tiddlywikis pagescroller:
`$tw.pageScroller.scrollIntoView(undefined, function() { return self.cm.cursorCoords(true,"window"); });`
* correct scrolling with tc-adjust-top-of-scroll
not multiplying `offset` with t causes jumps at the first animation steps, where the offset value is bigger than `endY - scrollPosition.y`
* correct scroll offset
* changes for global keyboardshortcuts
* add keyboard.js startup module
* remove not existing "th-opening-window" hook
* correct title
* use utils.addEventListeners
* define platform lookup-names on startup
* use the startup-lookup-names array
* use the platform-specific lookupNames only
* Update keyboard.js
* move initializations to the constructor
* move initializations to the constructor
* rename hasAnyTiddlerChanged
* don't explicitely create new RegExp
* use $tw.utils.hopArray
* match strings, no regex
* remove hopArray, move to boot.js
* add $tw.utils.hopArray to boot.js
* style update
* style updates
* move more to keyboardManager module
this could probably be moved to rootwidget.js
* move more to keyboardManager module
* add event listener for shortcuts in new windows
* prevent error when opening window is blocked
* add keydown listener on document in startup.js
* delete startup/keyboard.js
* add missing this.shortcutTiddlers
* Update keyboard.js
* Update boot.js
* add exports.hopArray to utils.js
* minor codingstyle tweak
* change how lookupnames get pushed to array
* Update windows.js
* re-add shortcuts-listener for new windows
I removed this before which I think was because I misunderstood what exactly should go to a separate PR
The bug here is that incoming tiddlers (ie tiddlers that were updated on the server and synced back to the browser) will retain any fields that are currently present but deleted in the incoming tiddler
To avoid clashing with tiddlers called "login-basic" :)
We also need to revise the rout for /status for the same reason, but there are backward compatibility issues there
* Added better handling for sortByList manual placements
If manual placement specifications show up in an inconvenient order,
sortByList, will go to the trouble of processing them in that order.
* Added tests to confirm solution to (#3296)
...That custom tag ordering will not choke when tiddlers get sorted after their dependencies have been placed around them
* Corrected list-after bug when referencing external titles
* Using more error-proof $tw.utils.hop in sortByList
* minor indentation correction in test-tags.js
Makes things a bit easier to follow when working in multiuser environments.
@inmysocks, @danielo515, @arlen22, @pmario, @drakor does this make sense for your use cases?
* Module-ize server routes and add static file support (#2510)
* Refactor server routes to modules
New module type: serverroute
Caveats: Loading order is not deterministic but this would only matter
if two route modules attempted to use the same path regexp (that would
be silly).
* Add static assets plugin
This plugin allows the node server to fetch static assets in the /assets
directory. I felt that this was a feature that goes above the core
functionality. That is why I added it as a plugin. with the modular
route extensions this was a breeze.
* Add serverroute description to ModuleTypes
* Coding standards tweaks
* Fix filename typo
* Move support for attachments from a plugin into the core
* Missing "else"
* Refactor server handling
* Introduce a new named parameter scheme for commands
* Move the SimpleServer class into it's own module
* Deprecate the --server command because of the unwieldy syntax
* Add a new --listen command using the new syntax
For example:
tiddlywiki mywiki --listen host:0.0.0.0 port:8090
* Add check for unknown parameters
* Add support for multiple basic authentication credentials in a CSV file
Beware: Passwords are stored in plain text. If that's a problem, use an authenticating proxy and the trusted header authentication approach.
* Refactor module locations
* Rename "serverroute" module type to "route"
* Remove support for verifying optional named command parameters
The idea was to be able to flag unknown parameter names, but requiring a command to pre-specify all the parameter names makes it harder for (say) the listen command to be extensible so that plugins can add new optional parameters that they handle. (This is particularly in the context of work in progress to encapsulate authenticators into their own modules).
* Refactor the two authenticators into separate modules and add support for authorization
* Correct mistaken path.join vs. path.resolve
See https://stackoverflow.com/a/39836259
* Docs for the named command parameters
I'd be grateful if anyone with sufficient Windows experience could confirm that the note about double quotes in "NamedCommandParameters" is correct.
* Be consistent about lower case parameter names
* Do the right thing when we have a username but no password
With a username parameter but no password parameter we'll attribute edits to that username, but not require authentication.
* Remove obsolete code
* Add support for requiring authentication without restricting the username
* Refactor authorization checks
* Return read_only status in /status response
* Fix two code typos
* Add basic support for detecting readonly status and avoiding write errors
We now have syncadaptors returning readonly status and avoid attempting to write to the server if it's going to fail
* Add readonly-styles
We hide editing-related buttons in read only mode
I've made this part of the tiddlyweb plugin but I think a case could be made for putting it into the core.
* Add custom request header as CSRF mitigation
By default we require the header X-Requested-With to be set to TiddlyWiki. Can be overriden by setting csrfdisable to "yes"
See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Protecting_REST_Services:_Use_of_Custom_Request_Headers
* Add support for HTTPS
* First pass at a route for serving rendered tiddlers
cc @Drakor
* Tweaks to the single tiddler static view
Adding a simple sidebar
* Switch to "dash" separated parameter names
* Typo
* Docs: Update ServerCommand and ListenCommand
* First pass at docs for the new web server stuff
Writing the docs is turning out to be quite an undertaking, much harder than writing the code!
* Get rid of extraneous paragraphs in static renderings
* Rejig anonymous user handling
Now we can support wikis that are read-only for anonymous access, but allow a user to login for read/write access.
* More docs
Slowly getting there...
* Static tiddler rendering: Fix HTML content in page title
* Docs updates
* Fix server command parameter names
Missed off 30ce7ea
* Docs: Missing quotes
* Avoid inadvertent dependency on Node.js > v9.6.0
The listenOptions parameter of the plain HTTP version of CreateServer was only introduced in v9.6.0
cc @Drakor @pmario
* Typo
* Refactored the is operator for simplicity and efficiency.
* Improve `is` filter documentation.
* Update is.js
* extracted `subops.length` to `num_of_subops`
* renamed `subop` to `operator` for clarity/differentiation from `subops`
* refactored to avoid using a `Set` object.
* Update is.js
* Fix WebDAV by requesting new ETag conditionally
For me. this was saving only the first time and subsequently failing.
Having revised the requests, I noticed it didn't get a new ETag after saving.
Seems not all WebDAV implementations return a new ETag in PUT requests.
In my WebDAV service (WsgiDAV) - ETag is only served from a HEAD
request.
So if no ETag is found with PUT - we request one with HEAD.
This patch fixes error handling and should also work with servers that
provide ETag directly upon PUT.
* Add tweak from PMario
* Adds a range widget
Adds a range widget that supports all the range attributes on a input[type=range] element. These include min max and increment.
* Update range.js
* Fix spaces vs tabs.
* Added documentation.
* Modify the is operator to allow multiple types to be specified.
* Fixed indentation.
* Fixed indentation.
* Rewritten to maintain input order when multiple filters provided.
* Updated documentation.
* Update is.tid
* Invoke hook when server starts
Invokes the `th-server-command-start` hook when the server is started, with the server object as the parameter. This allows adding a WebSocket listener to the server.
* Return the HTTP server from the listen function
Returns the node HTTP server created in the listen function to allow extension
* Add node HTTP server to server-command-start hook
* Change hook to post start in case we add a pre-start hook
* Create Hook__th-server-command-post-start.tid
* sets checked ckass for radio widget wrapper
* added tc-radio as standard class for radio widgets
* removed selectedClass again, as suggested
@pmario ;-)
* fixed the "0 is not a number bug" in listops and x-listops
* Fixed one comment
* "default" is not a good name for a variable
* Following code styles.
Moving getInt to utils.
* Removing unwanted spaces introduced by me
When occuring in a tiddler named "New Tiddler", the following construct should return ++ instead of +[[New Tiddler]]+
<$set name="myVariable" filter="[all[current]field:title[New Tiddler]]" value="">
+<<myVariable>>+
</$set>
Spending a bit more time with Chrome dev tools, and further to 254e1ca, this optimisation reduces the rendering time for the sample TOC from 1.9s to about 0.9s...
* extend ListWidget to enforce classes
Previously, the undocumented *class* attribute only allowed to specify
additional classes to be set.
Especially for use within a LinkCatcher, you can now apply / enforce
only the custom classes and avoid any of the defaults being applied
depending on the link target.
This will allow to implement #1161 more gracefully.
* use setClass insted of exclamation mark syntax
update docs & fix typo in docs
Remove URI encoding from PUT saver and let the browser handle it as necessary. This seems to be the normal way of doing things. We have confirmed that several WebDAV servers do not expect the file names to be double-encoded.
A first pass at fixing #2973 - comments are welcome. If everybody is
happy, the next step is to deprecate the existing
rendertiddler(s)/savetiddler(s) commands and replace them in all
examples and tiddlywiki.info files with the new equivalents.
This change makes it possible to perform the conversion from target
tiddler title to `href` value as a filter expression (previously a
JavaScript macro was needed to use the tv-get-export-link variable)
* Add ability to now macro to return same UTC string used in the modified and created fields.
* Revert "Add ability to now macro to return same UTC string used in the modified and created fields."
This reverts commit 7b6ad7db4a.
* Mods to formatDateString to adjust displayed date to UTC for [UTC]
format. Corresponding doc changes, and optimization for special
case.
document.location gives us an URL encoded version of the original
filename, so we decode it to recover the original filename for saving.
Fixes#2828Fixes#2819
* Trim tiddler titles imported via JSON
Otherwise, it's possible to create a tiddler with a trailing space (or a
leading one, I suppose) in its title. TiddlyWiki, in general, trims
titles before operating on a tiddler, so having a tiddler with a
trailing space ends up making that tiddler, for all intents and
purposes, uneditable.
Fixes GH #2850
* Signing the CLA
A couple of fixes:
* Fixed problem with loading saver in a file URI within Beaker
* Fixed problem when saving to a directory-style URI with an implicit
“/index.html”
* Switched to double quotes for strings
These changes allow drag and drop to work with one issue: <a> links are
not draggable; draggable divs, spans, buttons etc. seem to work fine.
There’s some issue with IE11 that I don’t understand.
For testing, you can force links to become spans by changing line 64 of
$:/core/modules/widgets/link.js to:
var domNode = this.document.createElement("span");
We do this so that we don’t accidentally modify shadow tiddlers when we
drag them to reorder them within their tag parent. Otherwise, moving a
toolbar button like $:/core/ui/Buttons/permaview in the control panel
will override the shadow tiddler.
At the moment, we support JSON files containing an array of tiddlers.
With this change the core will import files containing a single
tiddler. Also adding templates for saving individual tiddlers in JSON
format
The problem was that `this.responseText` crashes for non-text data. We
fix it by letting the client specify which property should be returned.
@ericshulman does this work for you?
* provides a "close plugin library" button
* starting from #1718 by @inmysocks
* possibly fixes all of #1718, #1597, and #2067
* corrected code comment
* add back title
No idea why I overlooked this beforehand.
Next time I will not suggest such changes that have little to do with
the PR, but rather just comment the code.
* ah, sorry, "fixed" wrong spot
now
```
<$action-sendmessage $message="tm-load-plugin-from-library"
url={{!!url}} title={{$(assetInfo)$!!original-title}}/>
```
...should be back at the right spot.
* mhhh... still fixing the mess
load, unload, puh... let's see if I got it now
* added unloadIFrame and minor syntax fixes
We now use highlight.js in raw HTML mode on the server, rather than
trying to use it with the fakedom. This causes problems with fakedoms
inability to get textContent for a node that has been created by
assigning innerHTML. So we extend the fakedom to allow the original
text content to be saved.
See #2778 for discussion.
I used this test:
console.time();for(var t=0; t<200; t++)
{$tw.wiki.filterTiddlers("[all[tiddlers+shadows]sameday[20170210]]");};c
onsole.timeEnd()
Before this patch, I got speeds of approx 190ms, versus 140ms
afterwards.
Note that the ability to add a cache property like this is only
possible because tiddler objects are immutable.
Like the load command except retrieves the file over HTTP/HTTPS.
Allows experimentation with server-side twederation
This is a cleaned up version of code that I wrote last year at TWEUM
2016 @inmysocks @pmario @twMat @xcazin
* putSaver: detect edit conflicts to prevent clobbering, if possible
if the server supplies an ETag, we send it back when saving, allowing
the server to detect edit conflicts and respond with 412 (cf.
https://www.w3.org/1999/04/Editing/)
caveats:
* this only kicks in after the first save, as we don't have access to
the ETag when first loading the document
* there's no recovery mechanism (e.g. resetting `this.etag` in order to
force clobbering), other than manually reloading the document
* putSaver: retrieve ETag upon initialization for clobbering protection
this addresses one of the caveats from the previous commit
(2d75cb83af) - while theoretically prone
to a race condition, it seems unlikely that saving will be triggered
before the server responds
* putSaver: simplify URI extraction
this simplifies the approach introduced in
f51f6bf774, with the purpose of removing
the fragment identifier
* putSaver: localize error message
* putSaver: switch to built-in HTTP helper
in the process, fixed ETag assignment in `#save` method (was
`this.etag`, now `self.etag`) as well as a syntax error due to a missing
closing brace
* putSaver: consolidate URI handling
The code here had got a bit broken by some PRs that I should have
checked more carefully. I’ve done a major refactoring which will
hopefully make it easier to understand, and fixes a number of problems:
* Problem with eg .md tiddlers not being deleted correctly
* Problem with Windows path separators not being usable within
$:/config/FileSystemPaths on Windows
* Problem with filename clashes not being detected correctly when
saving to a different directory via $:/config/FileSystemPaths
* Enables slashes within tiddler titles to be mapped into folders
* Enables plain text files like .md and .css to be saved with .meta
files instead of as .tid files (see #2558)
* No longer replaces spaces with underscores
As this is such a major update, I’d be grateful if Node.js users could
give it a careful run through — in particular, you’ll need to try
creating new tiddlers of various types and ensure that the expected
files are created.