OcttKB/Wiki-OcttKB/plugins/relink/$__plugins_flibbles_relink_js_utils.js

224 lines
6.4 KiB
JavaScript
Raw Normal View History

2023-06-11 22:14:59 +02:00
/*\
module-type: library
Utility methods for relink.
\*/
var macroFilter = "[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]";
/**This works nearly identically to $tw.modules.getModulesByTypeAsHashmap
* except that this also takes care of migrating V1 relink modules.
*/
exports.getModulesByTypeAsHashmap = function(moduleType, nameField) {
var results = Object.create(null);
$tw.modules.forEachModuleOfType(moduleType, function(title, module) {
var key = module[nameField];
if (key !== undefined) {
results[key] = module;
} else {
for (var entry in module) {
results[entry] = {
relink: module[entry],
report: function() {}};
results[entry][nameField] = entry;
}
}
});
return results;
};
exports.getTiddlerRelinkReferences = function(wiki, title, context) {
var tiddler = wiki.getTiddler(title),
references = Object.create(null),
options = {settings: context, wiki: wiki};
if (tiddler) {
try {
for (var relinker in getRelinkOperators()) {
getRelinkOperators()[relinker].report(tiddler, function(title, blurb) {
references[title] = references[title] || [];
references[title].push(blurb || '');
}, options);
}
} catch (e) {
if (e.message) {
e.message = e.message + "\nWhen reporting '" + title + "' Relink references";
}
throw e;
}
}
return references;
};
/** Returns a pair like this,
* { title: {field: entry, ... }, ... }
*/
exports.getRelinkResults = function(wiki, fromTitle, toTitle, context, tiddlerList, options) {
options = options || {};
options.wiki = options.wiki || wiki;
fromTitle = (fromTitle || "").trim();
toTitle = (toTitle || "").trim();
var changeList = Object.create(null);
if(fromTitle && toTitle !== undefined) {
if (tiddlerList === undefined) {
tiddlerList = wiki.getRelinkableTitles();
}
for (var i = 0; i < tiddlerList.length; i++) {
var title = tiddlerList[i];
var tiddler = wiki.getTiddler(title);
if(tiddler) {
try {
var entries = Object.create(null),
operators = getRelinkOperators();
options.settings = new Contexts.tiddler(wiki, context, title);
for (var operation in operators) {
operators[operation].relink(tiddler, fromTitle, toTitle, entries, options);
}
for (var field in entries) {
// So long as there is one key,
// add it to the change list.
if (tiddler.fields["plugin-type"]) {
// We never change plugins, even if they have links
changeList[title] = {};
changeList[title][field] = {impossible: true};
} else {
changeList[title] = entries;
}
break;
}
} catch (e) {
// Should we test for instanceof Error instead?: yes
// Does that work in the testing environment?: no
if (e.message) {
e.message = e.message + "\nWhen relinking '" + title + "'";
}
throw e;
}
}
}
}
return changeList;
};
var Contexts = $tw.modules.applyMethods('relinkcontext');
exports.getContext = function(name) {
return Contexts[name];
};
exports.getWikiContext = function(wiki) {
// This gives a fresh context every time. It is up to the indexer or
// the cache to preserve those contexts for as long as needed.
var whitelist = new Contexts.whitelist(wiki);
return new Contexts.import(wiki, whitelist, macroFilter);
};
/** Returns the Relink indexer, or a dummy object which pretends to be one.
*/
exports.getIndexer = function(wiki) {
if (!wiki._relink_indexer) {
wiki._relink_indexer = (wiki.getIndexer && wiki.getIndexer("RelinkIndexer")) || new (require('$:/plugins/flibbles/relink/js/utils/backupIndexer.js'))(wiki);
}
return wiki._relink_indexer;
};
/**Relinking supports a cache that persists throughout a whole relink op.
* This is because the Tiddlywiki caches may get wiped multiple times
* throughout the course of a relink.
*/
exports.getCacheForRun = function(options, cacheName, initializer) {
options.cache = options.cache || Object.create(null);
if (!$tw.utils.hop(options.cache, cacheName)) {
options.cache[cacheName] = initializer();
}
return options.cache[cacheName];
};
/**Returns a specific relinker.
* This is useful for wikitext rules which need to parse a filter or a list
*/
exports.getType = function(name) {
var Handler = getFieldTypes()[name];
return Handler ? new Handler() : undefined;
};
exports.getTypes = function() {
// We don't return fieldTypes, because we don't want it modified,
// and we need to filter out legacy names.
var rtn = Object.create(null);
for (var type in getFieldTypes()) {
var typeObject = getFieldTypes()[type];
rtn[typeObject.typeName] = typeObject;
}
return rtn;
};
exports.getDefaultType = function(wiki) {
var tiddler = wiki.getTiddler("$:/config/flibbles/relink/settings/default-type");
var defaultType = tiddler && tiddler.fields.text;
// make sure the default actually exists, otherwise default
return fieldTypes[defaultType] ? defaultType : "title";
};
exports.touchModifyField = function(wiki) {
var tiddler = wiki.getTiddler("$:/config/flibbles/relink/touch-modify");
return tiddler && tiddler.fields.text.trim() === "yes";
};
/**Given some text, and a param or attribute within that text, this returns
* what type of quotation that attribute is using.
*
* param: An object in the form {end:, ...}
*/
exports.determineQuote = function(text, param) {
var pos = param.end-1;
if (text[pos] === "'") {
return "'";
}
if (text[pos] === '"') {
if (text.substr(pos-2, 3) === '"""') {
return '"""';
} else {
return '"';
}
}
if (text.substr(pos-1,2) === ']]' && text.substr((pos-param.value.length)-3, 2) === '[[') {
return "[[";
}
return '';
};
var fieldTypes;
function getFieldTypes() {
if (!fieldTypes) {
fieldTypes = Object.create(null);
$tw.modules.forEachModuleOfType("relinkfieldtype", function(title, exports) {
function NewType() {};
NewType.prototype = exports;
NewType.typeName = exports.name;
fieldTypes[exports.name] = NewType;
// For legacy, if the NewType doesn't have a report method, we add one
if (!exports.report) {
exports.report = function() {};
}
// Also for legacy, some of the field types can go by other names
if (exports.aliases) {
$tw.utils.each(exports.aliases, function(alias) {
fieldTypes[alias] = NewType;
});
}
});
}
return fieldTypes;
}
var relinkOperators;
function getRelinkOperators() {
if (!relinkOperators) {
relinkOperators = exports.getModulesByTypeAsHashmap('relinkoperator', 'name');
}
return relinkOperators;
};