mirror of
https://github.com/Jermolene/TiddlyWiki5.git
synced 2026-04-27 15:50:53 -07:00
Merge branch 'master' into multi-wiki-support
This commit is contained in:
commit
2d4b3341f6
17 changed files with 428 additions and 95 deletions
26
core/modules/filters/backtranscludes.js
Normal file
26
core/modules/filters/backtranscludes.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*\
|
||||
title: $:/core/modules/filters/backtranscludes.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for returning all the backtranscludes from a tiddler
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.backtranscludes = function(source,operator,options) {
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
$tw.utils.pushTop(results,options.wiki.getTiddlerBacktranscludes(title));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
||||
26
core/modules/filters/transcludes.js
Normal file
26
core/modules/filters/transcludes.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*\
|
||||
title: $:/core/modules/filters/transcludes.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator for returning all the transcludes from a tiddler
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.transcludes = function(source,operator,options) {
|
||||
var results = new $tw.utils.LinkedList();
|
||||
source(function(tiddler,title) {
|
||||
results.pushTop(options.wiki.getTiddlerTranscludes(title));
|
||||
});
|
||||
return results.toArray();
|
||||
};
|
||||
|
||||
})();
|
||||
119
core/modules/indexers/back-indexer.js
Normal file
119
core/modules/indexers/back-indexer.js
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*\
|
||||
title: $:/core/modules/indexers/back-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
By parsing the tiddler text, indexes the tiddlers' back links, back transclusions, block level back links.
|
||||
|
||||
\*/
|
||||
function BackIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
BackIndexer.prototype.init = function() {
|
||||
this.subIndexers = {
|
||||
link: new BackSubIndexer(this,"extractLinks"),
|
||||
transclude: new BackSubIndexer(this,"extractTranscludes"),
|
||||
};
|
||||
};
|
||||
|
||||
BackIndexer.prototype.rebuild = function() {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.rebuild();
|
||||
});
|
||||
};
|
||||
|
||||
BackIndexer.prototype.update = function(updateDescriptor) {
|
||||
$tw.utils.each(this.subIndexers,function(subIndexer) {
|
||||
subIndexer.update(updateDescriptor);
|
||||
});
|
||||
};
|
||||
function BackSubIndexer(indexer,extractor) {
|
||||
this.wiki = indexer.wiki;
|
||||
this.indexer = indexer;
|
||||
this.extractor = extractor;
|
||||
/**
|
||||
* {
|
||||
* [target title, e.g. tiddler title being linked to]:
|
||||
* {
|
||||
* [source title, e.g. tiddler title that has link syntax in its text]: true
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.init = function() {
|
||||
// lazy init until first lookup
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype._init = function() {
|
||||
this.index = Object.create(null);
|
||||
var self = this;
|
||||
this.wiki.forEachTiddler(function(sourceTitle,tiddler) {
|
||||
var newTargets = self._getTarget(tiddler);
|
||||
$tw.utils.each(newTargets, function(target) {
|
||||
if(!self.index[target]) {
|
||||
self.index[target] = Object.create(null);
|
||||
}
|
||||
self.index[target][sourceTitle] = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.rebuild = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get things that is being referenced in the text, e.g. tiddler names in the link syntax.
|
||||
*/
|
||||
BackSubIndexer.prototype._getTarget = function(tiddler) {
|
||||
var parser = this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});
|
||||
if(parser) {
|
||||
return this.wiki[this.extractor](parser.tree);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.update = function(updateDescriptor) {
|
||||
// lazy init/update until first lookup
|
||||
if(!this.index) {
|
||||
return;
|
||||
}
|
||||
var newTargets = [],
|
||||
oldTargets = [],
|
||||
self = this;
|
||||
if(updateDescriptor.old.exists) {
|
||||
oldTargets = this._getTarget(updateDescriptor.old.tiddler);
|
||||
}
|
||||
if(updateDescriptor.new.exists) {
|
||||
newTargets = this._getTarget(updateDescriptor.new.tiddler);
|
||||
}
|
||||
|
||||
$tw.utils.each(oldTargets,function(target) {
|
||||
if(self.index[target]) {
|
||||
delete self.index[target][updateDescriptor.old.tiddler.fields.title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(newTargets,function(target) {
|
||||
if(!self.index[target]) {
|
||||
self.index[target] = Object.create(null);
|
||||
}
|
||||
self.index[target][updateDescriptor.new.tiddler.fields.title] = true;
|
||||
});
|
||||
}
|
||||
|
||||
BackSubIndexer.prototype.lookup = function(title) {
|
||||
if(!this.index) {
|
||||
this._init();
|
||||
}
|
||||
if(this.index[title]) {
|
||||
return Object.keys(this.index[title]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
exports.BackIndexer = BackIndexer;
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*\
|
||||
title: $:/core/modules/indexers/backlinks-indexer.js
|
||||
type: application/javascript
|
||||
module-type: indexer
|
||||
|
||||
Indexes the tiddlers' backlinks
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global modules: false */
|
||||
"use strict";
|
||||
|
||||
|
||||
function BacklinksIndexer(wiki) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.init = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.rebuild = function() {
|
||||
this.index = null;
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype._getLinks = function(tiddler) {
|
||||
var parser = this.wiki.parseText(tiddler.fields.type, tiddler.fields.text, {});
|
||||
if(parser) {
|
||||
return this.wiki.extractLinks(parser.tree);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.update = function(updateDescriptor) {
|
||||
if(!this.index) {
|
||||
return;
|
||||
}
|
||||
var newLinks = [],
|
||||
oldLinks = [],
|
||||
self = this;
|
||||
if(updateDescriptor.old.exists) {
|
||||
oldLinks = this._getLinks(updateDescriptor.old.tiddler);
|
||||
}
|
||||
if(updateDescriptor.new.exists) {
|
||||
newLinks = this._getLinks(updateDescriptor.new.tiddler);
|
||||
}
|
||||
|
||||
$tw.utils.each(oldLinks,function(link) {
|
||||
if(self.index[link]) {
|
||||
delete self.index[link][updateDescriptor.old.tiddler.fields.title];
|
||||
}
|
||||
});
|
||||
$tw.utils.each(newLinks,function(link) {
|
||||
if(!self.index[link]) {
|
||||
self.index[link] = Object.create(null);
|
||||
}
|
||||
self.index[link][updateDescriptor.new.tiddler.fields.title] = true;
|
||||
});
|
||||
}
|
||||
|
||||
BacklinksIndexer.prototype.lookup = function(title) {
|
||||
if(!this.index) {
|
||||
this.index = Object.create(null);
|
||||
var self = this;
|
||||
this.wiki.forEachTiddler(function(title,tiddler) {
|
||||
var links = self._getLinks(tiddler);
|
||||
$tw.utils.each(links, function(link) {
|
||||
if(!self.index[link]) {
|
||||
self.index[link] = Object.create(null);
|
||||
}
|
||||
self.index[link][title] = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
if(this.index[title]) {
|
||||
return Object.keys(this.index[title]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
exports.BacklinksIndexer = BacklinksIndexer;
|
||||
|
||||
})();
|
||||
|
|
@ -534,8 +534,8 @@ Return an array of tiddler titles that link to the specified tiddler
|
|||
*/
|
||||
exports.getTiddlerBacklinks = function(targetTitle) {
|
||||
var self = this,
|
||||
backlinksIndexer = this.getIndexer("BacklinksIndexer"),
|
||||
backlinks = backlinksIndexer && backlinksIndexer.lookup(targetTitle);
|
||||
backIndexer = this.getIndexer("BackIndexer"),
|
||||
backlinks = backIndexer && backIndexer.subIndexers.link.lookup(targetTitle);
|
||||
|
||||
if(!backlinks) {
|
||||
backlinks = [];
|
||||
|
|
@ -549,6 +549,68 @@ exports.getTiddlerBacklinks = function(targetTitle) {
|
|||
return backlinks;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that are directly transcluded within the given parse tree
|
||||
*/
|
||||
exports.extractTranscludes = function(parseTreeRoot) {
|
||||
// Count up the transcludes
|
||||
var transcludes = [],
|
||||
checkParseTree = function(parseTree, parentNode) {
|
||||
for(var t=0; t<parseTree.length; t++) {
|
||||
var parseTreeNode = parseTree[t];
|
||||
if(parseTreeNode.type === "transclude" && parseTreeNode.attributes.$tiddler && parseTreeNode.attributes.$tiddler.type === "string") {
|
||||
var value;
|
||||
// if it is Transclusion with Templates like `{{Index||$:/core/ui/TagTemplate}}`, the `$tiddler` will point to the template. We need to find the actual target tiddler from parent node
|
||||
if(parentNode && parentNode.type === "tiddler" && parentNode.attributes.tiddler && parentNode.attributes.tiddler.type === "string") {
|
||||
value = parentNode.attributes.tiddler.value;
|
||||
} else {
|
||||
value = parseTreeNode.attributes.$tiddler.value;
|
||||
}
|
||||
if(transcludes.indexOf(value) === -1) {
|
||||
transcludes.push(value);
|
||||
}
|
||||
}
|
||||
if(parseTreeNode.children) {
|
||||
checkParseTree(parseTreeNode.children, parseTreeNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
checkParseTree(parseTreeRoot);
|
||||
return transcludes;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that are transcluded from the specified tiddler
|
||||
*/
|
||||
exports.getTiddlerTranscludes = function(title) {
|
||||
var self = this;
|
||||
// We'll cache the transcludes so they only get computed if the tiddler changes
|
||||
return this.getCacheForTiddler(title,"transcludes",function() {
|
||||
// Parse the tiddler
|
||||
var parser = self.parseTiddler(title);
|
||||
if(parser) {
|
||||
return self.extractTranscludes(parser.tree);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Return an array of tiddler titles that transclude to the specified tiddler
|
||||
*/
|
||||
exports.getTiddlerBacktranscludes = function(targetTitle) {
|
||||
var self = this,
|
||||
backIndexer = this.getIndexer("BackIndexer"),
|
||||
backtranscludes = backIndexer && backIndexer.subIndexers.transclude.lookup(targetTitle);
|
||||
|
||||
if(!backtranscludes) {
|
||||
backtranscludes = [];
|
||||
}
|
||||
return backtranscludes;
|
||||
};
|
||||
|
||||
/*
|
||||
Return a hashmap of tiddler titles that are referenced but not defined. Each value is the number of times the missing tiddler is referenced
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue