Skip to content

Commit

Permalink
Major refactoring of filesystemadaptor
Browse files Browse the repository at this point in the history
The code here had got a bit broken by some PRs that I should have
checked more carefully. I’ve done a major refactoring which will
hopefully make it easier to understand, and fixes a number of problems:

* Problem with eg .md tiddlers not being deleted correctly
* Problem with Windows path separators not being usable within
$:/config/FileSystemPaths on Windows
* Problem with filename clashes not being detected correctly when
saving to a different directory via $:/config/FileSystemPaths
* Enables slashes within tiddler titles to be mapped into folders
* Enables plain text files like .md and .css to be saved with .meta
files instead of as .tid files (see #2558)
* No longer replaces spaces with underscores

As this is such a major update, I’d be grateful if Node.js users could
give it a careful run through — in particular, you’ll need to try
creating new tiddlers of various types and ensure that the expected
files are created.
  • Loading branch information
Jermolene committed Feb 11, 2017
1 parent 1961db6 commit 3708f6c
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 82 deletions.
79 changes: 78 additions & 1 deletion core/modules/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ exports.tagToCssSelector = function(tagName) {
});
};


/*
IE does not have sign function
*/
Expand Down Expand Up @@ -725,4 +724,82 @@ exports.strEndsWith = function(str,ending,position) {
}
};

/*
Transliterate string from eg. Cyrillic Russian to Latin
*/
var transliterationPairs = {
"Ё":"YO",
"Й":"I",
"Ц":"TS",
"У":"U",
"К":"K",
"Е":"E",
"Н":"N",
"Г":"G",
"Ш":"SH",
"Щ":"SCH",
"З":"Z",
"Х":"H",
"Ъ":"'",
"ё":"yo",
"й":"i",
"ц":"ts",
"у":"u",
"к":"k",
"е":"e",
"н":"n",
"г":"g",
"ш":"sh",
"щ":"sch",
"з":"z",
"х":"h",
"ъ":"'",
"Ф":"F",
"Ы":"I",
"В":"V",
"А":"a",
"П":"P",
"Р":"R",
"О":"O",
"Л":"L",
"Д":"D",
"Ж":"ZH",
"Э":"E",
"ф":"f",
"ы":"i",
"в":"v",
"а":"a",
"п":"p",
"р":"r",
"о":"o",
"л":"l",
"д":"d",
"ж":"zh",
"э":"e",
"Я":"Ya",
"Ч":"CH",
"С":"S",
"М":"M",
"И":"I",
"Т":"T",
"Ь":"'",
"Б":"B",
"Ю":"YU",
"я":"ya",
"ч":"ch",
"с":"s",
"м":"m",
"и":"i",
"т":"t",
"ь":"'",
"б":"b",
"ю":"yu"
};

exports.transliterate = function(str) {
return str.split("").map(function(char) {
return transliterationPairs[char] || char;
}).join("");
};

})();
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ type: text/vnd.tiddlywiki

By default, a [[TiddlyWiki on Node.js]] instance using a [[wiki folder|TiddlyWikiFolders]] will create new tiddler files by using the sanitised and disambiguated title as filename.

This can be customised by creating a tiddler [[$:/config/FileSystemPaths]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as a logical path to be used for the tiddler file. Logical paths don't include the `.tid` extension, and they always use `/` as directory separator (when generating the physical path, this is replaced by the correct separator for the platform ~TiddlyWiki is running on). If none of the filters matches, the logical path is simply the title with all occurences of `/` replaced by `_` (for backwards compatibility).
This can be customised by creating a tiddler [[$:/config/FileSystemPaths]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as a logical path to be used for the tiddler file. Logical paths don't include the `.tid` extension, and they can use `/` or `\` as directory separator (when generating the physical path, this is replaced by the correct separator for the platform ~TiddlyWiki is running on). If none of the filters matches, the logical path is simply the title with all occurences of `/` replaced by `_` (for backwards compatibility).

In both cases, the characters `<>:"\|?*^ ` are replaced by `_` in order to guarantee that the resulting path is legal on all supported platforms.
In both cases, the characters `<>:"\|?*^` are replaced by `_` in order to guarantee that the resulting path is legal on all supported platforms.

!! Example

Expand All @@ -21,3 +21,5 @@ In both cases, the characters `<>:"\|?*^ ` are replaced by `_` in order to guara
This will store newly created system tiddlers in `tiddlers/_system` (after stripping the `$:/` prefix), tiddlers tagged [[task]] in a subdirectory `tiddlers/mytasks`, and also create subdirectory structures for all other non-draft tiddlers.

Thus, $:/config/FileSystemPaths itself will end up in `tiddlers/_system/config/FileSystemPaths.tid` or `tiddlers\_system\config\FileSystemPaths.tid`, depending on the platform.

The final `[!has[draft.of]]` will match all remaining non-draft tiddlers. Because there was a match, any `/` or `\` in the tiddler title is mapped to a path separator. Thus, `some/thing/entirely/new` will be saved to `tiddlers/some/thing/entirely/new.tid` (ie, the file `new.tid` in a directory called `entirely`).
146 changes: 67 additions & 79 deletions plugins/tiddlywiki/filesystem/filesystemadaptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,113 +35,107 @@ FileSystemAdaptor.prototype.getTiddlerInfo = function(tiddler) {
return {};
};

$tw.config.typeInfo = {
"text/vnd.tiddlywiki": {
fileType: "application/x-tiddler",
extension: ".tid"
}
};
/*
Return a fileInfo object for a tiddler, creating it if necessary:
filepath: the absolute path to the file containing the tiddler
type: the type of the tiddler file (NOT the type of the tiddler -- see below)
hasMetaFile: true if the file also has a companion .meta file
The boot process populates $tw.boot.files for each of the tiddler files that it loads. The type is found by looking up the extension in $tw.config.fileExtensionInfo (eg "application/x-tiddler" for ".tid" files).
It is the responsibility of the filesystem adaptor to update $tw.boot.files for new files that are created.
*/
FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) {
// See if we've already got information about this file
var self = this,
title = tiddler.fields.title,
fileInfo = $tw.boot.files[title];
// Get information about how to save tiddlers of this type
var type = tiddler.fields.type || "text/vnd.tiddlywiki";
var typeInfo = $tw.config.typeInfo[type] ||
$tw.config.contentTypeInfo[type] ||
$tw.config.typeInfo["text/vnd.tiddlywiki"];
var extension = typeInfo.extension || "";
if(!fileInfo) {
// If not, we'll need to generate it
if(fileInfo) {
// If so, just invoke the callback
callback(null,fileInfo);
} else {
// Otherwise, we'll need to generate it
fileInfo = {};
var tiddlerType = tiddler.fields.type || "text/vnd.tiddlywiki";
// Get the content type info
var contentTypeInfo = $tw.config.contentTypeInfo[tiddlerType] || {};
// Get the file type by looking up the extension
var extension = contentTypeInfo.extension || ".tid";
fileInfo.type = $tw.config.fileExtensionInfo[extension].type;
// Use a .meta file unless we're saving a .tid file.
// (We would need more complex logic if we supported other template rendered tiddlers besides .tid)
fileInfo.hasMetaFile = (fileInfo.type !== "application/x-tiddler");
// Generate the base filepath and ensure the directories exist
var baseFilepath = path.resolve($tw.boot.wikiTiddlersPath,this.generateTiddlerBaseFilepath(title));
$tw.utils.createDirectory(baseFilepath);
// Start by getting a list of the existing files in the directory
fs.readdir($tw.boot.wikiTiddlersPath,function(err,files) {
fs.readdir(path.dirname(baseFilepath),function(err,files) {
if(err) {
return callback(err);
}
// Assemble the new fileInfo
fileInfo = {};
fileInfo.filepath = $tw.boot.wikiTiddlersPath + path.sep + self.generateTiddlerFilename(title,extension,files);
fileInfo.type = typeInfo.fileType || tiddler.fields.type;
fileInfo.hasMetaFile = typeInfo.hasMetaFile;
// Save the newly created fileInfo
// Start with the base filename plus the extension
var filepath = baseFilepath;
if(filepath.substr(-extension.length).toLocaleLowerCase() !== extension.toLocaleLowerCase()) {
filepath = filepath + extension;
}
var filename = path.basename(filepath),
count = 1;
// Add a discriminator if we're clashing with an existing filename while
// handling case-insensitive filesystems (NTFS, FAT/FAT32, etc.)
while(files.some(function(value) {return value.toLocaleLowerCase() === filename.toLocaleLowerCase();})) {
filepath = baseFilepath + " " + (count++) + extension;
filename = path.basename(filepath);
}
// Set the final fileInfo
fileInfo.filepath = filepath;
console.log("\x1b[1;35m" + "For " + title + ", type is " + fileInfo.type + " hasMetaFile is " + fileInfo.hasMetaFile + " filepath is " + fileInfo.filepath + "\x1b[0m");
$tw.boot.files[title] = fileInfo;
// Pass it to the callback
callback(null,fileInfo);
});
} else {
// Otherwise just invoke the callback
callback(null,fileInfo);
}
};

/*
Transliterate string from cyrillic russian to latin
*/
var transliterate = function(cyrillyc) {
var a = {"Ё":"YO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"SH","Щ":"SCH","З":"Z","Х":"H","Ъ":"'","ё":"yo","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"sh","щ":"sch","з":"z","х":"h","ъ":"'","Ф":"F","Ы":"I","В":"V","А":"a","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"ZH","Э":"E","ф":"f","ы":"i","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"zh","э":"e","Я":"Ya","Ч":"CH","С":"S","М":"M","И":"I","Т":"T","Ь":"'","Б":"B","Ю":"YU","я":"ya","ч":"ch","с":"s","м":"m","и":"i","т":"t","ь":"'","б":"b","ю":"yu"};
return cyrillyc.split("").map(function (char) {
return a[char] || char;
}).join("");
};

/*
Given a list of filters, apply every one in turn to source, and return the first result of the first filter with non-empty result.
*/
FileSystemAdaptor.prototype.findFirstFilter = function(filters,source) {
var numFilters = filters.length;
for(var i=0; i<numFilters; i++) {
for(var i=0; i<filters.length; i++) {
var result = this.wiki.filterTiddlers(filters[i],null,source);
if(result.length > 0) {
return result[0];
}
}
return null;
};

/*
Add file extension to a file path if it doesn't already exist.
*/
FileSystemAdaptor.addFileExtension = function(file,extension) {
return $tw.utils.strEndsWith(file,extension) ? file : file + extension;
};


/*
Given a tiddler title and an array of existing filenames, generate a new legal filename for the title, case insensitively avoiding the array of existing filenames
*/
FileSystemAdaptor.prototype.generateTiddlerFilename = function(title,extension,existingFilenames) {
FileSystemAdaptor.prototype.generateTiddlerBaseFilepath = function(title) {
var baseFilename;
// Check whether the user has configured a tiddler -> pathname mapping
var pathNameFilters = this.wiki.getTiddlerText("$:/config/FileSystemPaths");
if(pathNameFilters) {
var source = this.wiki.makeTiddlerIterator([title]);
var result = this.findFirstFilter(pathNameFilters.split("\n"),source);
if(result) {
// interpret "/" as path separator
baseFilename = result.replace(/\//g,path.sep);
baseFilename = this.findFirstFilter(pathNameFilters.split("\n"),source);
console.log("baseFilename",baseFilename)
if(baseFilename) {
// Interpret "/" and "\" as path separator
baseFilename = baseFilename.replace(/\/|\\/g,path.sep);
}
}
if(!baseFilename) {
// no mapping configured, or it did not match this tiddler
// in this case, we fall back to legacy behaviour
baseFilename = title.replace(/\//g,"_");
// No mappings provided, or failed to match this tiddler so we use title as filename
baseFilename = title.replace(/\/|\\/g,"_");
}
// Remove any of the characters that are illegal in Windows filenames
var baseFilename = transliterate(baseFilename.replace(/<|>|\:|\"|\\|\||\?|\*|\^|\s/g,"_"));
var baseFilename = $tw.utils.transliterate(baseFilename.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_"));
// Truncate the filename if it is too long
if(baseFilename.length > 200) {
baseFilename = baseFilename.substr(0,200);
}
// Start with the base filename plus the extension
var filename = FileSystemAdaptor.addFileExtension(baseFilename,extension),
count = 1;
// Add a discriminator if we're clashing with an existing filename while
// handling case-insensitive filesystems (NTFS, FAT/FAT32, etc.)
while(existingFilenames.some(function(value) {return value.toLocaleLowerCase() === filename.toLocaleLowerCase();})) {
filename = baseFilename + " " + (count++) + extension;
}
return filename;
return baseFilename;
};

/*
Expand All @@ -150,45 +144,39 @@ Save a tiddler and invoke the callback with (err,adaptorInfo,revision)
FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) {
var self = this;
this.getTiddlerFileInfo(tiddler,function(err,fileInfo) {
var template, content, encoding, filepath,
_finish = function() {
callback(null, {}, 0);
};
if(err) {
return callback(err);
}
var error = $tw.utils.createDirectory(path.dirname(fileInfo.filepath));
var filepath = fileInfo.filepath,
error = $tw.utils.createDirectory(path.dirname(filepath));
if(error) {
return callback(error);
}
var typeInfo = $tw.config.contentTypeInfo[fileInfo.type];
if(fileInfo.hasMetaFile || typeInfo.encoding === "base64") {
if(fileInfo.hasMetaFile) {
// Save the tiddler as a separate body and meta file
filepath = fileInfo.filepath;
var typeInfo = $tw.config.contentTypeInfo[tiddler.fields.type || "text/plain"] || {encoding: "utf8"};
fs.writeFile(filepath,tiddler.fields.text,{encoding: typeInfo.encoding},function(err) {
if(err) {
return callback(err);
}
content = self.wiki.renderTiddler("text/plain","$:/core/templates/tiddler-metadata",{variables: {currentTiddler: tiddler.fields.title}});
filepath = FileSystemAdaptor.addFileExtension(fileInfo.filepath,".meta");
fs.writeFile(filepath,content,{encoding: "utf8"},function (err) {
fs.writeFile(fileInfo.filepath + ".meta",content,{encoding: "utf8"},function (err) {
if(err) {
return callback(err);
}
self.logger.log("Saved file",filepath);
_finish();
return callback(null);
});
});
} else {
// Save the tiddler as a self contained templated file
content = self.wiki.renderTiddler("text/plain","$:/core/templates/tid-tiddler",{variables: {currentTiddler: tiddler.fields.title}});
filepath = FileSystemAdaptor.addFileExtension(fileInfo.filepath,".tid");
var content = self.wiki.renderTiddler("text/plain","$:/core/templates/tid-tiddler",{variables: {currentTiddler: tiddler.fields.title}});
fs.writeFile(filepath,content,{encoding: "utf8"},function (err) {
if(err) {
return callback(err);
}
self.logger.log("Saved file",filepath);
_finish();
return callback(null);
});
}
});
Expand Down Expand Up @@ -219,14 +207,14 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) {
self.logger.log("Deleted file",fileInfo.filepath);
// Delete the metafile if present
if(fileInfo.hasMetaFile) {
fs.unlink(FileSystemAdaptor.addFileExtension(fileInfo.filepath,".meta"),function(err) {
fs.unlink(fileInfo.filepath + ".meta",function(err) {
if(err) {
return callback(err);
}
$tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);
});
} else {
$tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);
return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback);
}
});
} else {
Expand Down

28 comments on commit 3708f6c

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a short check with.

cd path/to/tw/source
node tiddlywiki.js editions/server --server

and get the following behaviour:


Mario@pc-mario MINGW64 /d/git/tiddly/tiddlywiki/TiddlyWiki5 (master)
$ node tiddlywiki.js editions/server --server
Serving on 127.0.0.1:8080
(press ctrl-C to exit)
syncer-server-filesystem: Dispatching 'save' task: $:/StoryList
For $:/StoryList, type is application/x-tiddler hasMetaFile is false filepath is D:\git\tiddly\tiddlywiki\TiddlyWiki5\ed
itions\server\tiddlers\$__StoryList.tid
FileSystem: Saved file D:\git\tiddly\tiddlywiki\TiddlyWiki5\editions\server\tiddlers\$__StoryList.tid
syncer-server-filesystem: Dispatching 'save' task: $:/StoryList
FileSystem: Saved file D:\git\tiddly\tiddlywiki\TiddlyWiki5\editions\server\tiddlers\$__StoryList.tid
syncer-server-filesystem: Dispatching 'save' task: $:/StoryList
FileSystem: Saved file D:\git\tiddly\tiddlywiki\TiddlyWiki5\editions\server\tiddlers\$__StoryList.tid
syncer-server-filesystem: Dispatching 'save' task: Draft of 'New Tiddler'
For Draft of 'New Tiddler', type is application/x-tiddler hasMetaFile is false filepath is D:\git\tiddly\tiddlywiki\Tidd
lyWiki5\editions\server\tiddlers\Draft of 'New Tiddler'.tid
FileSystem: Saved file D:\git\tiddly\tiddlywiki\TiddlyWiki5\editions\server\tiddlers\Draft of 'New Tiddler'.tid

There are files $__StoryList.tid and Draft of 'New Tiddler'.tid plus 2 new unneeded directories with the same names, without .tid extension.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I rename "draft of new tiddler" to "asdf" also an asdf directory is created and the Draft of 'New Tiddler' director is not deleted.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system is win10 with git shell, which is MINGW64.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same test with win10 powershell -> same results.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nodejs version is 4.5.0 both systems

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did test all different type fields. ... They all seem to create the right file / metafile combinations.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to work as intended. But may be a side effect of the above.

title: $:/config/FileSystemPaths
type: text/vnd.tiddlywiki

[!is[system]addprefix[x/]]

I'll stop testing for now.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

files created in the explorer by hand.
then start the server and open localhost

test.sh  

# some comment for testing
test.sh.meta

title: test.sh
type: text/plain

produces wrong type. .. type: .sh type should be: text/plain

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposal

Since the type field is essential now, it should be set to text/vnd.tiddlywiki by default.
If a tiddler is saved that way it should be saved as "asdf.tid"

If a tiddler has no type field it should be saved as "asdf" and "asdf.meta"
This is consistent and it is possible to create files without an extension.

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pmario

This doesn't seem to work as intended. But may be a side effect of the above.

title: $:/config/FileSystemPaths
type: text/vnd.tiddlywiki

[!is[system]addprefix[x/]]

That works for me, could you try again? Any useful debugging output

produces wrong type. .. type: .sh type should be: text/plain

Confirmed, am investigating now. I also verified that it works in 5.1.13

Since the type field is essential now,

It is not intended to be essential (once the bugs are ironed out).

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

produces wrong type. .. type: .sh type should be: text/plain

This is fixed in d5b04c2

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did test it again with latest master d5b04c2 ... and the problem with the additional directories is gone. .. That's strange.

You are right. This line alone works.

[!is[system]addprefix[x/]]

I actually did test this and missed the 3rd line :/

[is[system]removeprefix[$:/]addprefix[_system/]]
[tag[task]addprefix[mytasks/]]
[!has[draft.of]]
[!is[system]addprefix[x/]]

line 4 doesn't work, since [!has[draft.of]] grabs the "token" ... So that's a problem. We need to document this behaviour, a little bit better.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs states:

Thus, $:/config/FileSystemPaths itself will end up in tiddlers/_system/config/FileSystemPaths.tid or tiddlers\_system\config\FileSystemPaths.tid, depending on the platform.

but if the workflow is like this:

  • create a new tiddler: $:/config/FileSystemPaths
  • content: [tag[task]addprefix[mytasks/]] ... no other lines
  • save and test
  • open the config tiddler
  • add the rest
  • save and test again: -> the config tiddler didn't move.

**So imo that's a problem. ** ... That's the exact workflow as I did test it yesterday.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following workflow also causes a problem:

  • create a new tiddler: $:/config/FileSystemPaths
  • content: [tag[task]addprefix[mytasks/]] ... no other lines
  • save config tiddler
  • create tiddler: asdf tagged: task and save
  • tiddler: asdf is moved to mytasks -> OK
  • open asdf and remove the tag
  • tiddler is still at mytasks directory

IMO that's a bug

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also see an other problem.

Since eg: test.txt and test.txt.meta are 2 different files now, the save operation is not atomic anymore. ...

So we will run into all kind of strange consistency problems with systems, that use a caching mechanism to write files (OSes) and systems that watch file IO to tirgger actions. eg: file syncing software.

Those problems will be rare, practically impossible to reproduce and that's why they will be extremely hard to find.

just some thoughts

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pmario

line 4 doesn't work, since [!has[draft.of]] grabs the "token" ... So that's a problem. We need to document this behaviour, a little bit better.

Hmmm it's a cascade that stops at the first match; do you mean that that is a problem, or the docs?

save and test again: -> the config tiddler didn't move.

These settings affect the filename chosen for a new tiddler. Tiddlers that were originally loaded from a file at startup are always saved back to that file.

Note that this behaviour hasn't changed.

Since eg: test.txt and test.txt.meta are 2 different files now, the save operation is not atomic anymore. ...

We've always saved a separate .meta file eg for JPGs. All that this change does is use the technique for all recognised file types.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm it's a cascade that stops at the first match; do you mean that that is a problem, or the docs?

I'm not sure. ... Both versions may cause unexpected behaviour. So let's stick to the actual behaviour and improve the docs.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These settings affect the filename chosen for a new tiddler. Tiddlers that were originally loaded from a file at startup are always saved back to that file.

Note that this behaviour hasn't changed.

You are right. I just forgot about that :)

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pmario any help on docs gratefully received 😄

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've always saved a separate .meta file eg for JPGs. All that this change does is use the technique for all recognised file types.

Hmmm, I missed this behaviour. I thought images created with TW have been saved as .tid files. ...

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried, that users have completely wrong expectations about this feature. So we may label it as: "Experts use only!" at the moment.

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I missed this behaviour. I thought images created with TW have been saved as .tid files. ...

Until this commit, only .JPG files were saved as separate files with a .meta file. That commit introduced a few other problems, but broadened the support to all binary files.

I'm worried, that users have completely wrong expectations about this feature. So we may label it as: "Experts use only!" at the moment.

Well, if there's a specific misunderstanding that we can anticipate, the docs could provide a cautionary note. Your example above might be a good example to include in the docs.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jermolene
How can we switch off the 2 files feature. I personally don't want to deal with 2 different files. .. at least not all the time.

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can we switch off the 2 files feature. I personally don't want to deal with 2 different files. .. at least not all the time.

We'd have to make it configurable... 😅

There are many plausible options: some people might like to switch to JSON instead of .tid...

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't want to deal with 2 different files. .. at least not all the time.

The advantages are quite compelling, though. It means that one gets syntax highlighting when working on CSS/JS/HTML tiddler files in an external editor, for example.

@pmario
Copy link
Contributor

@pmario pmario commented on 3708f6c Feb 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The advantages are quite compelling, though. It means that one gets syntax highlighting when working on CSS/JS/HTML tiddler files in an external editor, for example.

You are right. ... but it also opens an other attack vector: eg: test.cmd, test.bat, test.ps1 are executables in windows systems. .. and if test.ps1 was created by the user or node.js on behalf of the user, there are almost no security checks.

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @pmario I was going to say "there are currently no executable file types registered in boot.js, so files like test.cmd, test.bat, test.ps1 will be created as .tid files", but then I checked and found that they are erroneously getting created as test.cmd.txt etc. I'll investigate and fix.

@Jermolene
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it is the expected behaviour; the files import as 'text/plain' and so are exported as .tid files.

Please sign in to comment.