Coding Conventions
This is an attempt to capture the somewhat eccentric coding conventions that are used in the TiddlyWiki core code. See also NamingConventions.
Lint "correctness"
TiddlyWiki code should normally have no warnings ore errors when checked with http://www.javascriptlint.com/ (when checked with the following two warnings switched off)
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) -inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
Layout
The K&R Layout convention is used. It has been choosen because it is the most compact of the standard layout conventions. (Source code compactness matters for TiddlyWiki, since the source code is in every TiddlyWiki file.)
Whitespace
1) Indentation should be by tabs not spaces. Tab width is 4 spaces.
2) There is no whitespace between a keyword and any following bracket, eg: while(true)...
3) There should be whitespace around assignment and conditional operators, eg:
var a = b;
if(b < c)
function safariSaveFile(url,content)
{
url = safariFilenameToUrl(url);
var plugin = document.embeds["tiddlyWikiSafariSaver"];
return plugin.writeStringToURL(content,url);
}
4) Exception to rule (3): in a for statement there is no space around the conditional operators and a space follows the ';' (eg):
for(var i=0; i<t.length; i++)...
5) The opening/closing brace of a function is at column 1, content at 1 tab indent
function safariSaveFile(url,content)
{
url = safariFilenameToUrl(url);
var plugin = document.embeds["tiddlyWikiSafariSaver"];
return plugin.writeStringToURL(content,url);
}
6) No extra spaces next to '(', ')', ', ?', ',', ';'
function safariSaveFile(url,content)
{
url = safariFilenameToUrl(url);
var plugin = document.embeds["tiddlyWikiSafariSaver"];
return plugin.writeStringToURL(content,url);
}
Line breaks
Long statements may be broken after an operator. Continuation statements should be indented by two tabs from original statement (and not aligned to the assignment operator).
Semicolons (';') should not be omitted if the syntax allows it
Especially at the end of a function definition like this:
Tiddler.prototype.escapeLineBreaks = function()
{
return this.text.escapeLineBreaks();
}; // this semicolon may/shall not be omitted.
Conditional assignment
Conditional assigment is prefered when it can be used.
Return statements
Return values should not be enclosed in brackets eg return false; not return(false);
Example
Wikifier.prototype.example = function(output)
{
...
while(formatterMatch) {
this.matchText = formatterMatch[0];
...
for(var i=1; i<formatterMatch.length; i++) {
if(formatterMatch[i]) {
this.formatter.formatters[i-1].handler(this);
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
break;
}
}
formatterMatch = this.formatter.formatterRegExp.exec(this.source);
}
if(a < b) {
this.nextMatch = this.source.length*2;
} else if(a < c) {
this.nextMatch = this.source.length+4;
} else {
this.nextMatch = this.source.length;
}
}
Comments should be capitalised and punctuated normally
Although trailing punctuation should be omitted:
// Do something. And then another thing
And not:
// do something. and then another thing.
Naming conventions
See also NamingConventions.
Arrays are plural, elements of the array are singular
var results = [];
...
var result = results[i];
If applicable the name of the catch variable is "ex" (not "e")
function operaLoadFile(filePath)
{
var content = [];
try {
var r = new java.io.BufferedReader(new java.io.FileReader(operaUrlToFilename(filePath)));
var line;
while ((line = r.readLine()) != null)
content.push(new String(line));
r.close();
} catch(ex) {
if(window.opera)
opera.postError(ex);
return null;
}
return content.join("\n");
}
And finally... break the rules when you need to
The primary aim of all of these rules is to help make the readability of code; sometimes readability can be enhanced by breaking the rules. For example, here's an extract from the SHA-1 hash function that purposefully shunts multiple statements onto a line because they are, in effect, partial inlines of the SHA-1 round functions:
for(j=60;j<80;j++)
{
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5((a>>>27)|(a<<5),b^c^d,e,w[j],k4);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}