From a5e9ef9b5f1dc3dd7bc9dc1e331d5c5ebc5ed2c5 Mon Sep 17 00:00:00 2001 From: Jermolene Date: Sat, 3 May 2014 11:32:55 +0100 Subject: [PATCH] Adopt new URL scheme for permalinks Instead of using `%00` as a separator we do the more conventional `#!:`. --- core/modules/startup.js | 91 ++++++++++--------- core/modules/widgets/navigator.js | 10 +- core/modules/wiki.js | 19 +++- .../tw5.com/tiddlers/concepts/PermaLinks.tid | 25 ++++- 4 files changed, 88 insertions(+), 57 deletions(-) diff --git a/core/modules/startup.js b/core/modules/startup.js index ad87ea148..49146d943 100755 --- a/core/modules/startup.js +++ b/core/modules/startup.js @@ -25,6 +25,8 @@ var DEFAULT_HISTORY_TITLE = "$:/HistoryList"; // Default tiddlers var DEFAULT_TIDDLERS_TITLE = "$:/DefaultTiddlers"; +// Favicon tiddler +var FAVICON_TITLE = "$:/favicon.ico"; var widget = require("$:/core/modules/widgets/widget.js"); @@ -75,34 +77,37 @@ exports.startup = function() { // Clear outstanding tiddler store change events to avoid an unnecessary refresh cycle at startup $tw.wiki.clearTiddlerEventQueue(); // Decode the hash portion of our URL - var parts = []; + var target, + storyFilter; if($tw.locationHash.charAt(1) === "!") { - parts = decodeURIComponent($tw.locationHash.substr(2)).split("\u0000") + var hash = $tw.locationHash.substr(2), + split = hash.indexOf(":"); + if(split === -1) { + target = decodeURIComponent(hash.trim()); + } else { + target = decodeURIComponent(hash.substr(0,split - 1).trim()); + storyFilter = decodeURIComponent(hash.substr(split + 1).trim()); + } } - if(parts[0]) { - // Set the history - var historyList = [{title: parts[0]}]; - $tw.wiki.setTiddlerData(DEFAULT_HISTORY_TITLE, historyList, {"current-tiddler": parts[0]}); - // Set the story - var story = []; - for(var t=1; t 0) { + targetTiddler = historyList[historyList.length-1].title; + } + location.hash = "#!" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList)); +} + /* Main render function for PageMacros, which includes the PageTemplate */ diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index bfe8b40be..2225a88ce 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -133,15 +133,7 @@ title: a title string or an array of title strings fromPageRect: page coordinates of the origin of the navigation */ NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) { - var titles = $tw.utils.isArray(title) ? title : [title]; - // Add a new record to the top of the history stack - if(this.historyTitle) { - var historyList = this.wiki.getTiddlerData(this.historyTitle,[]); - $tw.utils.each(titles,function(title) { - historyList.push({title: title, fromPageRect: fromPageRect}); - }); - this.wiki.setTiddlerData(this.historyTitle,historyList,{"current-tiddler": titles[titles.length-1]}); - } + this.wiki.addToHistory(title,fromPageRect,this.historyTitle); }; /* diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 22938e38b..09a843bde 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1070,7 +1070,7 @@ exports.readFile = function(file,callback) { /* Check whether the specified draft tiddler has been modified */ -$tw.Wiki.prototype.isDraftModified = function(title) { +exports.isDraftModified = function(title) { var tiddler = this.getTiddler(title); if(!tiddler.isDraft()) { return false; @@ -1091,4 +1091,21 @@ $tw.Wiki.prototype.isDraftModified = function(title) { }); }; +/* +Add a new record to the top of the history stack +title: a title string or an array of title strings +fromPageRect: page coordinates of the origin of the navigation +historyTitle: title of history tiddler (defaults to $:/HistoryList) +*/ +exports.addToHistory = function(title,fromPageRect,historyTitle) { + historyTitle = historyTitle || "$:/HistoryList"; + var titles = $tw.utils.isArray(title) ? title : [title]; + // Add a new record to the top of the history stack + var historyList = this.getTiddlerData(historyTitle,[]); + $tw.utils.each(titles,function(title) { + historyList.push({title: title, fromPageRect: fromPageRect}); + }); + this.setTiddlerData(historyTitle,historyList,{"current-tiddler": titles[titles.length-1]}); +}; + })(); diff --git a/editions/tw5.com/tiddlers/concepts/PermaLinks.tid b/editions/tw5.com/tiddlers/concepts/PermaLinks.tid index 7d7990931..2b29744d5 100644 --- a/editions/tw5.com/tiddlers/concepts/PermaLinks.tid +++ b/editions/tw5.com/tiddlers/concepts/PermaLinks.tid @@ -6,6 +6,8 @@ type: text/vnd.tiddlywiki Permalinks allow direct links to individual tiddlers within a TiddlyWiki. +! Simple Permalinks + The simplest form of permalink is a single target tiddler title appended to the base URL with "#!": http://tiddlywiki.com/#!HelloThere @@ -14,13 +16,26 @@ The tiddler title can contain spaces if required: [[http://tiddlywiki.com/#!Using TiddlyWiki on Node.js]] -The permalink can also specify the story list of tiddlers that should be opened alongside the target tiddler. The tiddler titles are separated by `%00`: +Note that double square brackets are not required around the target tiddler title; however, if present they are silently removed. -http://tiddlywiki.com/#!Tiddlers%00Tags%00TiddlerFields%00Tiddlers +! Story Permalinks -In this form, the first tiddler title is taken to be the target tiddler, and the remaining titles give the sequence of tiddlers in the story list. +The permalink can also specify the story list of tiddlers that should be opened alongside the target tiddler as a [[TiddlerFilter|TiddlerFilters]]: + +[[http://tiddlywiki.com/#!TiddlerFields:Tiddlers TiddlerTags TiddlerFields ContentType]] If the target tiddler isn't present in the story list then it is automatically inserted at the top. This means that the following two examples both target the tiddler `Tiddlers` within the story sequence `Tiddlers`, `Tags`, `TiddlerFields`: -http://tiddlywiki.com/#!Tiddlers%00Tags%00TiddlerFields -http://tiddlywiki.com/#!Tiddlers%00Tiddlers%00Tags%00TiddlerFields +[[http://tiddlywiki.com/#!Tiddlers:Tags TiddlerFields]] + +[[http://tiddlywiki.com/#!Tiddlers:Tiddlers Tags TiddlerFields]] + +It is also possible to specify a story filter without specifying a target tiddler for navigation: + +~http://tiddlywiki.com/#!:[tags[task]] + +! About URL encoding + +There are technical restrictions on the legal characters in an URL fragment. To allow all tiddler titles to be addressed, illegal characters are subject to a process called "URL encoding" whereby problematic characters are replaced by their numeric code. For example, the space character is replaced with `%20`. + +Both the target tiddler title and the story filter should be URL encoded (but not the separating colon). TiddlyWiki generates properly encoded URLs which can look quite ugly. However, in practice browsers will usually perfectly happily process arbitrary characters in URL fragments. Thus when creating permalinks manually you can choose to ignore URL encoding.