Add "external-attachments" plugin

This plugin provides support for importing tiddlers as external attachments -- it only works on platforms such as TiddlyDesktop that provide the required "path" property with imported files.

Using the plugin means that instead of importing binary files as self-contained tiddlers, they are imported as "skinny" tiddlers that reference the original file via the ''_canonical_uri'' field. This reduces the size of the wiki and thus improves performance. However, it does mean that the wiki is no longer fully self-contained
This commit is contained in:
Jermolene 2017-10-11 17:54:03 +01:00
parent 518f57f4bb
commit e646d207c3
6 changed files with 147 additions and 1 deletions

View File

@ -14,7 +14,8 @@
"tiddlywiki/qrcode",
"tiddlywiki/bibtex",
"tiddlywiki/savetrail",
"tiddlywiki/twitter"
"tiddlywiki/twitter",
"tiddlywiki/external-attachments"
],
"themes": [
"tiddlywiki/vanilla",

View File

@ -0,0 +1,6 @@
title: $:/config/ExternalAttachments/
Enable: yes
UseAbsoluteForDescendents: no
UseAbsoluteForNonDescendents: no

View File

@ -0,0 +1,7 @@
{
"title": "$:/plugins/tiddlywiki/external-attachments",
"description": "External attachment support for TiddlyDesktop et al.",
"author": "Jeremy Ruston",
"core-version": ">=5.0.0",
"list": "readme settings"
}

View File

@ -0,0 +1,10 @@
title: $:/plugins/tiddlywiki/external-attachments/readme
! Introduction
This plugin provides support for importing tiddlers as external attachments. That means that instead of importing binary files as self-contained tiddlers, they are imported as "skinny" tiddlers that reference the original file via the ''_canonical_uri'' field. This reduces the size of the wiki and thus improves performance. However, it does mean that the wiki is no longer fully self-contained.
! Compatibility
This plugin only works when using TiddlyWiki with platforms such as TiddlyDesktop that support the ''path'' attribute for imported/dragged files.

View File

@ -0,0 +1,11 @@
title: $:/plugins/tiddlywiki/external-attachments/settings
When used on platforms that provide the necessary support (such as ~TiddlyDesktop), you can optionally import binary files as external tiddlers that reference the original file via the ''_canonical_uri'' field.
By default, a relative path is used to reference the file. Optionally, you can specify that an absolute path is used instead. You can do this separately for "descendent" attachments -- files that are contained within the directory containing the wiki -- vs. "non-descendent" attachments.
<$checkbox tiddler="$:/config/ExternalAttachments/Enable" field="text" checked="yes" unchecked="no" default="no"> <$link to="$:/config/ExternalAttachments/Enable">Enable importing binary files as external attachments</$link> </$checkbox>
<$checkbox tiddler="$:/config/ExternalAttachments/UseAbsoluteForDescendents" field="text" checked="yes" unchecked="no" default="no"> <$link to="$:/config/ExternalAttachments/UseAbsoluteForDescendents">Use absolute paths for descendent attachments</$link> </$checkbox>
<$checkbox tiddler="$:/config/ExternalAttachments/UseAbsoluteForNonDescendents" field="text" checked="yes" unchecked="no" default="no"> <$link to="$:/config/ExternalAttachments/UseAbsoluteForNonDescendents">Use absolute paths for non-descendent attachments</$link> </$checkbox>

View File

@ -0,0 +1,111 @@
/*\
title: $:/plugins/tiddlywiki/external-attachments/startup.js
type: application/javascript
module-type: startup
Startup initialisation
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var ENABLE_EXTERNAL_ATTACHMENTS_TITLE = "$:/config/ExternalAttachments/Enable",
USE_ABSOLUTE_FOR_DESCENDENTS_TITLE = "$:/config/ExternalAttachments/UseAbsoluteForDescendents",
USE_ABSOLUTE_FOR_NON_DESCENDENTS_TITLE = "$:/config/ExternalAttachments/UseAbsoluteForNonDescendents";
// Export name and synchronous status
exports.name = "external-attachments";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
exports.startup = function() {
test_makePathRelative();
$tw.hooks.addHook("th-importing-file",function(info) {
if(document.location.protocol === "file:" && info.isBinary && info.file.path && $tw.wiki.getTiddlerText(ENABLE_EXTERNAL_ATTACHMENTS_TITLE,"") === "yes") {
var locationPathParts = document.location.pathname.split("/").slice(0,-1),
filePathParts = info.file.path.split(/[\\\/]/mg).map(encodeURIComponent);
info.callback([
{
title: info.file.name,
type: info.type,
"_canonical_uri": makePathRelative(
filePathParts.join("/"),
locationPathParts.join("/"),
{
useAbsoluteForNonDescendents: $tw.wiki.getTiddlerText(USE_ABSOLUTE_FOR_NON_DESCENDENTS_TITLE,"") === "yes",
useAbsoluteForDescendents: $tw.wiki.getTiddlerText(USE_ABSOLUTE_FOR_DESCENDENTS_TITLE,"") === "yes"
}
)
}
]);
return true;
} else {
return false;
}
});
};
/*
Given a source absolute path and a root absolute path, returns the source path expressed as a relative path from the root path.
*/
function makePathRelative(sourcepath,rootpath,options) {
options = options || {};
var sourceParts = sourcepath.split("/"),
rootParts = rootpath.split("/"),
outputParts = [];
// Check that each path started with a slash
if(sourceParts[0] || rootParts[0]) {
throw "makePathRelative: both paths must be absolute";
}
// Identify any common portion from the start
var c = 1,
p;
while(c < sourceParts.length && c < rootParts.length && sourceParts[c] === rootParts[c]) {
c += 1;
}
// Return "." if there's nothing left
if(c === sourceParts.length && c === rootParts.length ) {
return "."
}
// Use an absolute path if required
if((options.useAbsoluteForNonDescendents && c < rootParts.length) || (options.useAbsoluteForDescendents && c === rootParts.length)) {
return sourcepath;
}
// Move up a directory for each directory left in the root
for(p = c; p < rootParts.length; p++) {
outputParts.push("..");
}
// Add on the remaining parts of the source path
for(p = c; p < sourceParts.length; p++) {
outputParts.push(sourceParts[p]);
}
return outputParts.join("/");
}
function test_makePathRelative() {
var msg = "makePathRelative test failed";
if(makePathRelative("/Users/me/something","/Users/you/something") !== "../../me/something") {
throw msg;
}
if(makePathRelative("/Users/me/something","/Users/you/something",{useAbsoluteForNonDescendents: true}) !== "/Users/me/something") {
throw msg;
}
if(makePathRelative("/Users/me/something/else","/Users/me/something") !== "else") {
throw msg;
}
if(makePathRelative("/Users/me/something","/Users/me/something/new") !== "..") {
throw msg;
}
if(makePathRelative("/Users/me/something","/Users/me/something/new",{useAbsoluteForNonDescendents: true}) !== "/Users/me/something") {
throw msg;
}
if(makePathRelative("/Users/me/something","/Users/me/something") !== ".") {
throw msg;
}
}
})();