tiddlywiki-production
Version:
a non-linear personal web notebook
1 lines • 11.1 kB
JavaScript
$tw.preloadTiddler({"title":"$:/plugins/tiddlywiki/freelinks","name":"Freelinks","description":"Freelinking of tiddler titles","list":"readme settings","version":"5.1.22","plugin-type":"plugin","dependents":"","type":"application/json","text":"{\"tiddlers\":{\"$:/config/Freelinks/Enable\":{\"title\":\"$:/config/Freelinks/Enable\",\"text\":\"yes\"},\"$:/plugins/tiddlywiki/freelinks/macros/view\":{\"title\":\"$:/plugins/tiddlywiki/freelinks/macros/view\",\"tags\":\"$:/tags/Macro/View\",\"text\":\"<$set name=\\\"tv-freelinks\\\" value={{$:/config/Freelinks/Enable}}/>\\n\"},\"$:/core/modules/widgets/plain-text.js\":{\"title\":\"$:/core/modules/widgets/plain-text.js\",\"text\":\"/*\\\\\\ntitle: $:/core/modules/widgets/plain-text.js\\ntype: application/javascript\\nmodule-type: widget\\n\\nA copy of the core text widget under a different name\\n\\n\\\\*/\\n(function(){\\n\\n/*jslint node: true, browser: true */\\n/*global $tw: false */\\n\\\"use strict\\\";\\n\\nvar Widget = require(\\\"$:/core/modules/widgets/widget.js\\\").widget;\\n\\nvar PlainTextNodeWidget = function(parseTreeNode,options) {\\n\\tthis.initialise(parseTreeNode,options);\\n};\\n\\n/*\\nInherit from the base widget class\\n*/\\nPlainTextNodeWidget.prototype = new Widget();\\n\\n/*\\nRender this widget into the DOM\\n*/\\nPlainTextNodeWidget.prototype.render = function(parent,nextSibling) {\\n\\tthis.parentDomNode = parent;\\n\\tthis.computeAttributes();\\n\\tthis.execute();\\n\\tvar text = this.getAttribute(\\\"text\\\",this.parseTreeNode.text || \\\"\\\");\\n\\ttext = text.replace(/\\\\r/mg,\\\"\\\");\\n\\tvar textNode = this.document.createTextNode(text);\\n\\tparent.insertBefore(textNode,nextSibling);\\n\\tthis.domNodes.push(textNode);\\n};\\n\\n/*\\nCompute the internal state of the widget\\n*/\\nPlainTextNodeWidget.prototype.execute = function() {\\n\\t// Nothing to do for a text node\\n};\\n\\n/*\\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\\n*/\\nPlainTextNodeWidget.prototype.refresh = function(changedTiddlers) {\\n\\tvar changedAttributes = this.computeAttributes();\\n\\tif(changedAttributes.text) {\\n\\t\\tthis.refreshSelf();\\n\\t\\treturn true;\\n\\t} else {\\n\\t\\treturn false;\\t\\n\\t}\\n};\\n\\nexports[\\\"plain-text\\\"] = PlainTextNodeWidget;\\n\\n})();\\n\",\"type\":\"application/javascript\",\"module-type\":\"widget\"},\"$:/plugins/tiddlywiki/freelinks/readme\":{\"title\":\"$:/plugins/tiddlywiki/freelinks/readme\",\"text\":\"This plugin adds automatic generation of links to tiddler titles.\\n\\n''Note that automatic link generation can be very slow when there are a large number of tiddlers''.\\n\\nFreelinking is activated for runs of text that have the following variables set:\\n\\n* `tv-wikilinks` is NOT equal to `no`\\n* `tv-freelinks` is set to `yes`\\n\\nFreelinks are case sensitive.\\n\\nWithin view templates, the variable `tv-freelinks` is automatically set to the content of $:/config/Freelinks/Enable, which can be set via the settings panel of this plugin.\\n\\n!! Notes\\n\\nTo change within which tiddlers freelinking occurs requires customising the shadow tiddler $:/plugins/tiddlywiki/freelinks/macros/view. This tiddler is tagged $:/tags/Macro/View which means that it will be included as a local macro in each view template. By default, its content is:\\n\\n```\\n<$set name=\\\"tv-freelinks\\\" value={{$:/config/Freelinks/Enable}}/>\\n```\\n\\nThat means that for each tiddler the variable tv-freelinks will be set to the tiddler $:/config/Freelinks/Enable, which is set to \\\"yes\\\" or \\\"no\\\" by the settings in control panel.\\n\\nInstead, we can use a filter expression to, say, only freelink within the tiddler with the title \\\"HelloThere\\\":\\n\\n```\\n<$set name=\\\"tv-freelinks\\\" value={{{ [<currentTiddler>match[HelloThere]then[yes]else[no]] }}}/>\\n```\\n\\nOr, we can make a filter that will only freelink within tiddlers with the tag \\\"MyTag\\\":\\n\\n```\\n<$set name=\\\"tv-freelinks\\\" value={{{ [<currentTiddler>tag[MyTags]then[yes]else[no]] }}}/>\\n```\\n\\nOr we can combine both approaches:\\n\\n```\\n<$set name=\\\"tv-freelinks\\\" value={{{ [<currentTiddler>match[HelloThere]] ~[<currentTiddler>tag[MyTag]] +[then[yes]else[no]] }}}/>\\n```\\n\"},\"$:/plugins/tiddlywiki/freelinks/settings\":{\"title\":\"$:/plugins/tiddlywiki/freelinks/settings\",\"text\":\"<$checkbox tiddler=\\\"$:/config/Freelinks/Enable\\\" field=\\\"text\\\" checked=\\\"yes\\\" unchecked=\\\"no\\\" default=\\\"no\\\"> <$link to=\\\"$:/config/Freelinks/Enable\\\">Enable freelinking within tiddler view templates</$link> </$checkbox>\\n\"},\"$:/plugins/tiddlywiki/freelinks/styles\":{\"title\":\"$:/plugins/tiddlywiki/freelinks/styles\",\"tags\":\"[[$:/tags/Stylesheet]]\",\"text\":\"\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\nbutton.tc-tiddlylink.tc-freelink, a.tc-tiddlylink.tc-freelink {\\n\\tbackground-color: #5777d91c;\\n}\\n\"},\"$:/core/modules/widgets/text.js\":{\"title\":\"$:/core/modules/widgets/text.js\",\"text\":\"/*\\\\\\ntitle: $:/core/modules/widgets/text.js\\ntype: application/javascript\\nmodule-type: widget\\n\\nAn override of the core text widget that automatically linkifies the text\\n\\n\\\\*/\\n(function(){\\n\\n/*jslint node: true, browser: true */\\n/*global $tw: false */\\n\\\"use strict\\\";\\n\\nvar Widget = require(\\\"$:/core/modules/widgets/widget.js\\\").widget,\\n\\tLinkWidget = require(\\\"$:/core/modules/widgets/link.js\\\").link,\\n\\tButtonWidget = require(\\\"$:/core/modules/widgets/button.js\\\").button;\\n\\nvar TextNodeWidget = function(parseTreeNode,options) {\\n\\tthis.initialise(parseTreeNode,options);\\n};\\n\\n/*\\nInherit from the base widget class\\n*/\\nTextNodeWidget.prototype = new Widget();\\n\\n/*\\nRender this widget into the DOM\\n*/\\nTextNodeWidget.prototype.render = function(parent,nextSibling) {\\n\\tthis.parentDomNode = parent;\\n\\tthis.computeAttributes();\\n\\tthis.execute();\\n\\tthis.renderChildren(parent,nextSibling);\\n};\\n\\n/*\\nCompute the internal state of the widget\\n*/\\nTextNodeWidget.prototype.execute = function() {\\n\\tvar self = this;\\n\\t// Get our parameters\\n\\tvar childParseTree = [{\\n\\t\\t\\ttype: \\\"plain-text\\\",\\n\\t\\t\\ttext: this.getAttribute(\\\"text\\\",this.parseTreeNode.text || \\\"\\\")\\n\\t\\t}];\\n\\t// Only process links if not disabled and we're not within a button or link widget\\n\\tif(this.getVariable(\\\"tv-wikilinks\\\",{defaultValue:\\\"yes\\\"}).trim() !== \\\"no\\\" && this.getVariable(\\\"tv-freelinks\\\",{defaultValue:\\\"no\\\"}).trim() === \\\"yes\\\" && !this.isWithinButtonOrLink()) {\\n\\t\\t// Get the information about the current tiddler titles, and construct a regexp\\n\\t\\tthis.tiddlerTitleInfo = this.wiki.getGlobalCache(\\\"tiddler-title-info\\\",function() {\\n\\t\\t\\tvar titles = [],\\n\\t\\t\\t\\treparts = [],\\n\\t\\t\\t\\tsortedTitles = self.wiki.allTitles().sort(function(a,b) {\\n\\t\\t\\t\\t\\tvar lenA = a.length,\\n\\t\\t\\t\\t\\t\\tlenB = b.length;\\n\\t\\t\\t\\t\\t// First sort by length, so longer titles are first\\n\\t\\t\\t\\t\\tif(lenA !== lenB) {\\n\\t\\t\\t\\t\\t\\tif(lenA < lenB) {\\n\\t\\t\\t\\t\\t\\t\\treturn +1;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\treturn -1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t// Then sort alphabetically within titles of the same length\\n\\t\\t\\t\\t\\t\\tif(a < b) {\\n\\t\\t\\t\\t\\t\\t\\treturn -1;\\n\\t\\t\\t\\t\\t\\t} else if(a > b) {\\n\\t\\t\\t\\t\\t\\t\\treturn +1;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t$tw.utils.each(sortedTitles,function(title) {\\n\\t\\t\\t\\tif(title.substring(0,3) !== \\\"$:/\\\") {\\n\\t\\t\\t\\t\\ttitles.push(title);\\n\\t\\t\\t\\t\\treparts.push(\\\"(\\\\\\\\b\\\" + $tw.utils.escapeRegExp(title) + \\\"\\\\\\\\b)\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\treturn {\\n\\t\\t\\t\\ttitles: titles,\\n\\t\\t\\t\\tregexp: new RegExp(reparts.join(\\\"|\\\"),\\\"\\\")\\n\\t\\t\\t};\\n\\t\\t});\\n\\t\\t// Repeatedly linkify\\n\\t\\tif(this.tiddlerTitleInfo.titles.length > 0) {\\n\\t\\t\\tvar index,text,match,matchEnd;\\n\\t\\t\\tdo {\\n\\t\\t\\t\\tindex = childParseTree.length - 1;\\n\\t\\t\\t\\ttext = childParseTree[index].text;\\n\\t\\t\\t\\tmatch = this.tiddlerTitleInfo.regexp.exec(text);\\n\\t\\t\\t\\tif(match) {\\n\\t\\t\\t\\t\\t// Make a text node for any text before the match\\n\\t\\t\\t\\t\\tif(match.index > 0) {\\n\\t\\t\\t\\t\\t\\tchildParseTree[index].text = text.substring(0,match.index);\\n\\t\\t\\t\\t\\t\\tindex += 1;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t// Make a link node for the match\\n\\t\\t\\t\\t\\tchildParseTree[index] = {\\n\\t\\t\\t\\t\\t\\ttype: \\\"link\\\",\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\tto: {type: \\\"string\\\", value: match[0]},\\n\\t\\t\\t\\t\\t\\t\\t\\\"class\\\": {type: \\\"string\\\", value: \\\"tc-freelink\\\"}\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tchildren: [{\\n\\t\\t\\t\\t\\t\\t\\ttype: \\\"plain-text\\\", text: match[0]\\n\\t\\t\\t\\t\\t\\t}]\\n\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tindex += 1;\\n\\t\\t\\t\\t\\t// Make a text node for any text after the match\\n\\t\\t\\t\\t\\tmatchEnd = match.index + match[0].length;\\n\\t\\t\\t\\t\\tif(matchEnd < text.length) {\\n\\t\\t\\t\\t\\t\\tchildParseTree[index] = {\\n\\t\\t\\t\\t\\t\\t\\ttype: \\\"plain-text\\\",\\n\\t\\t\\t\\t\\t\\t\\ttext: text.substring(matchEnd)\\n\\t\\t\\t\\t\\t\\t};\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} while(match && childParseTree[childParseTree.length - 1].type === \\\"plain-text\\\");\\t\\t\\t\\n\\t\\t}\\n\\t}\\n\\t// Make the child widgets\\n\\tthis.makeChildWidgets(childParseTree);\\n};\\n\\nTextNodeWidget.prototype.isWithinButtonOrLink = function() {\\n\\tvar withinButtonOrLink = false,\\n\\t\\twidget = this.parentWidget;\\n\\twhile(!withinButtonOrLink && widget) {\\n\\t\\twithinButtonOrLink = widget instanceof ButtonWidget || widget instanceof LinkWidget;\\n\\t\\twidget = widget.parentWidget;\\n\\t}\\n\\treturn withinButtonOrLink;\\n};\\n\\n/*\\nSelectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering\\n*/\\nTextNodeWidget.prototype.refresh = function(changedTiddlers) {\\n\\tvar self = this,\\n\\t\\tchangedAttributes = this.computeAttributes(),\\n\\t\\ttitlesHaveChanged = false;\\n\\t$tw.utils.each(changedTiddlers,function(change,title) {\\n\\t\\tif(change.isDeleted) {\\n\\t\\t\\ttitlesHaveChanged = true\\n\\t\\t} else {\\n\\t\\t\\ttitlesHaveChanged = titlesHaveChanged || !self.tiddlerTitleInfo || self.tiddlerTitleInfo.titles.indexOf(title) === -1;\\n\\t\\t}\\n\\t});\\n\\tif(changedAttributes.text || titlesHaveChanged) {\\n\\t\\tthis.refreshSelf();\\n\\t\\treturn true;\\n\\t} else {\\n\\t\\treturn false;\\t\\n\\t}\\n};\\n\\nexports.text = TextNodeWidget;\\n\\n})();\\n\",\"type\":\"application/javascript\",\"module-type\":\"widget\"}}}"});