13 Mar 2012 cdent   » (Master)

_tiddlywiki-apps.js

//
// Please note:
//
// * This code is designed to be readable but for compactness it only includes brief comments. You can see fuller comments
//   in the project repository at https://github.com/TiddlyWiki/tiddlywiki
//
// * You should never need to modify this source code directly. TiddlyWiki is carefully designed to allow deep customisation
//   without changing the core code. Please consult the development group at http://groups.google.com/group/TiddlyWikiDev
//
// JSLint directives
/*global jQuery:false, version:false */
/*jslint bitwise:true, browser:true, confusion:true, eqeq:true, evil:true, forin:true, maxerr:100, plusplus:true, regexp:true, sloppy:true, sub:true, undef:true, unparam:true, vars:true, white:true */
//--
//-- Configuration repository
//--

// Miscellaneous options
var config = {
	numRssItems: 20, // Number of items in the RSS feed
	animDuration: 400, // Duration of UI animations in milliseconds
	cascadeFast: 20, // Speed for cascade animations (higher == slower)
	cascadeSlow: 60, // Speed for EasterEgg cascade animations
	cascadeDepth: 5, // Depth of cascade animation
	locale: "en" // W3C language tag
};

// Hashmap of alternative parsers for the wikifier
config.parsers = {};

// Adaptors
config.adaptors = {};
config.defaultAdaptor = null;

// Backstage tasks
config.tasks = {};

// Annotations
config.annotations = {};

// Custom fields to be automatically added to new tiddlers
config.defaultCustomFields = {};

// Messages
config.messages = {
	messageClose: {},
	dates: {},
	tiddlerPopup: {}
};

// Options that can be set in the options panel and/or cookies
config.options = {
	chkRegExpSearch: false,
	chkCaseSensitiveSearch: false,
	chkIncrementalSearch: true,
	chkAnimate: true,
	chkSaveBackups: true,
	chkAutoSave: false,
	chkGenerateAnRssFeed: false,
	chkSaveEmptyTemplate: false,
	chkOpenInNewWindow: true,
	chkToggleLinks: false,
	chkHttpReadOnly: false,
	chkForceMinorUpdate: false,
	chkConfirmDelete: true,
	chkInsertTabs: false,
	chkUsePreForStorage: true, // Whether to use 
 format for storage
	chkDisplayInstrumentation: false,
	txtBackupFolder: "",
	txtEditorFocus: "text",
	txtMainTab: "tabTimeline",
	txtMoreTab: "moreTabAll",
	txtMaxEditRows: "30",
	txtFileSystemCharSet: "UTF-8",
	txtTheme: ""
	};
config.optionsDesc = {};

config.optionsSource = {};

// Default tiddler templates
var DEFAULT_VIEW_TEMPLATE = 1;
var DEFAULT_EDIT_TEMPLATE = 2;
config.tiddlerTemplates = {
	1: "ViewTemplate",
	2: "EditTemplate"
};

// More messages (rather a legacy layout that should not really be like this)
config.views = {
	wikified: {
		tag: {}
	},
	editor: {
		tagChooser: {}
	}
};

// Backstage tasks
config.backstageTasks = ["save","sync","importTask","tweak","plugins"];

// Extensions
config.extensions = {};

// Macros; each has a 'handler' member that is inserted later
config.macros = {
	today: {},
	version: {},
	search: {sizeTextbox: 15},
	tiddler: {},
	tag: {},
	tags: {},
	tagging: {},
	timeline: {},
	allTags: {},
	list: {
		all: {},
		missing: {},
		orphans: {},
		shadowed: {},
		touched: {},
		filter: {}
	},
	closeAll: {},
	permaview: {},
	saveChanges: {},
	slider: {},
	option: {},
	options: {},
	newTiddler: {},
	newJournal: {},
	tabs: {},
	gradient: {},
	message: {},
	view: {defaultView: "text"},
	edit: {},
	tagChooser: {},
	toolbar: {},
	plugins: {},
	refreshDisplay: {},
	importTiddlers: {},
	upgrade: {
		source: "http://tiddlywiki-releases.tiddlyspace.com/upgrade",
		backupExtension: "pre.core.upgrade"
	},
	sync: {},
	annotations: {}
};

// Commands supported by the toolbar macro
config.commands = {
	closeTiddler: {},
	closeOthers: {},
	editTiddler: {},
	saveTiddler: {hideReadOnly: true},
	cancelTiddler: {},
	deleteTiddler: {hideReadOnly: true},
	permalink: {},
	references: {type: "popup"},
	jump: {type: "popup"},
	syncing: {type: "popup"},
	fields: {type: "popup"}
};

// Control of macro parameter evaluation
config.evaluateMacroParameters = "all";

// Basic regular expressions
config.textPrimitives = {
	upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
	lowerLetter: "[a-z0-9_\\-\u00df-\u00ff\u0151\u0171]",
	anyLetter:   "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
	anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]"
};
if(!((new RegExp("[\u0150\u0170]","g")).test("\u0150"))) {
	config.textPrimitives = {
		upperLetter: "[A-Z\u00c0-\u00de]",
		lowerLetter: "[a-z0-9_\\-\u00df-\u00ff]",
		anyLetter:   "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff]",
		anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff]"
	};
}
config.textPrimitives.sliceSeparator = "::";
config.textPrimitives.sectionSeparator = "##";
config.textPrimitives.urlPattern = "(?:file|http|https|mailto|ftp|irc|news|data):[^\\s'\"]+(?:/|\\b)";
config.textPrimitives.unWikiLink = "~";
config.textPrimitives.wikiLink = "(?:(?:" + config.textPrimitives.upperLetter + "+" +
	config.textPrimitives.lowerLetter + "+" +
	config.textPrimitives.upperLetter +
	config.textPrimitives.anyLetter + "*)|(?:" +
	config.textPrimitives.upperLetter + "{2,}" +
	config.textPrimitives.lowerLetter + "+))";

config.textPrimitives.cssLookahead = "(?:(" + config.textPrimitives.anyLetter + "+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + config.textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
config.textPrimitives.cssLookaheadRegExp = new RegExp(config.textPrimitives.cssLookahead,"mg");

config.textPrimitives.brackettedLink = "\\[\\[([^\\]]+)\\]\\]";
config.textPrimitives.titledBrackettedLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" + config.textPrimitives.titledBrackettedLink + ")|(?:" +
	config.textPrimitives.brackettedLink + ")|(?:" +
	config.textPrimitives.urlPattern + ")","mg");
config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+ config.textPrimitives.wikiLink + ")|(?:" +
	config.textPrimitives.titledBrackettedLink + ")|(?:" +
	config.textPrimitives.brackettedLink + ")|(?:" +
	config.textPrimitives.urlPattern + ")","mg");

config.glyphs = {
	currBrowser: null,
	browsers: [],
	codes: {}
};

//--
//-- Shadow tiddlers
//--

config.shadowTiddlers = {
	StyleSheet: "",
	MarkupPreHead: "",
	MarkupPostHead: "",
	MarkupPreBody: "",
	MarkupPostBody: "",
	TabTimeline: '>',
	TabAll: '>',
	TabTags: '>',
	TabMoreMissing: '>',
	TabMoreOrphans: '>',
	TabMoreShadowed: '>',
	AdvancedOptions: '>',
	PluginManager: '>',
	SystemSettings: '',
	ToolbarCommands: '|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|\n|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|',
	WindowTitle: '> - >'
};

// Browser detection... In a very few places, there's nothing else for it but to know what browser we're using.
config.userAgent = navigator.userAgent.toLowerCase();
config.browser = {
	isIE: config.userAgent.indexOf("msie") != -1 && config.userAgent.indexOf("opera") == -1,
	isGecko: navigator.product == "Gecko" && config.userAgent.indexOf("WebKit") == -1,
	ieVersion: /MSIE (\d.\d)/i.exec(config.userAgent), // config.browser.ieVersion[1], if it exists, will be the IE version string, eg "6.0"
	isSafari: config.userAgent.indexOf("applewebkit") != -1,
	isBadSafari: !((new RegExp("[\u0150\u0170]","g")).test("\u0150")),
	firefoxDate: /gecko\/(\d{8})/i.exec(config.userAgent), // config.browser.firefoxDate[1], if it exists, will be Firefox release date as "YYYYMMDD"
	isOpera: config.userAgent.indexOf("opera") != -1,
	isChrome: config.userAgent.indexOf('chrome') > -1,
	isLinux: config.userAgent.indexOf("linux") != -1,
	isUnix: config.userAgent.indexOf("x11") != -1,
	isMac: config.userAgent.indexOf("mac") != -1,
	isWindows: config.userAgent.indexOf("win") != -1
};

merge(config.glyphs,{
	browsers: [
		function() {return config.browser.isIE;},
		function() {return true;}
		],
	codes: {
		downTriangle: ["\u25BC","\u25BE"],
		downArrow: ["\u2193","\u2193"],
		bentArrowLeft: ["\u2190","\u21A9"],
		bentArrowRight: ["\u2192","\u21AA"]
	}
});

//--
//-- Translateable strings
//--

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

merge(config.options,{
	txtUserName: "YourName"});

merge(config.tasks,{
	save: {text: "save", tooltip: "Save your changes to this TiddlyWiki"},
	importTask: {text: "import", tooltip: "Import tiddlers and plugins from other TiddlyWiki files and servers", content: '>'},
	tweak: {text: "tweak", tooltip: "Tweak the appearance and behaviour of TiddlyWiki", content: '>'},
	upgrade: {text: "upgrade", tooltip: "Upgrade TiddlyWiki core code", content: '>'},
	plugins: {text: "plugins", tooltip: "Manage installed plugins", content: '>'}
});

// Options that can be set in the options panel and/or cookies
merge(config.optionsDesc,{
	txtUserName: "Username for signing your edits",
	chkRegExpSearch: "Enable regular expressions for searches",
	chkCaseSensitiveSearch: "Case-sensitive searching",
	chkIncrementalSearch: "Incremental key-by-key searching",
	chkAnimate: "Enable animations",
	chkSaveBackups: "Keep backup file when saving changes",
	chkAutoSave: "Automatically save changes",
	chkGenerateAnRssFeed: "Generate an RSS feed when saving changes",
	chkSaveEmptyTemplate: "Generate an empty template when saving changes",
	chkOpenInNewWindow: "Open external links in a new window",
	chkToggleLinks: "Clicking on links to open tiddlers causes them to close",
	chkHttpReadOnly: "Hide editing features when viewed over HTTP",
	chkForceMinorUpdate: "Don't update modifier username and date when editing tiddlers",
	chkConfirmDelete: "Require confirmation before deleting tiddlers",
	chkInsertTabs: "Use the tab key to insert tab characters instead of moving between fields",
	txtBackupFolder: "Name of folder to use for backups",
	txtMaxEditRows: "Maximum number of rows in edit boxes",
	txtTheme: "Name of the theme to use",
	txtFileSystemCharSet: "Default character set for saving changes (Firefox/Mozilla only)"});

merge(config.messages,{
	customConfigError: "Problems were encountered loading plugins. See PluginManager for details",
	pluginError: "Error: %0",
	pluginDisabled: "Not executed because disabled via 'systemConfigDisable' tag",
	pluginForced: "Executed because forced via 'systemConfigForce' tag",
	pluginVersionError: "Not executed because this plugin needs a newer version of TiddlyWiki",
	nothingSelected: "Nothing is selected. You must select one or more items first",
	savedSnapshotError: "It appears that this TiddlyWiki has been incorrectly saved. Please see http://www.tiddlywiki.com/#Download for details",
	subtitleUnknown: "(unknown)",
	undefinedTiddlerToolTip: "The tiddler '%0' doesn't yet exist",
	shadowedTiddlerToolTip: "The tiddler '%0' doesn't yet exist, but has a pre-defined shadow value",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "External link to %0",
	noTags: "There are no tagged tiddlers",
	notFileUrlError: "You need to save this TiddlyWiki to a file before you can save changes",
	cantSaveError: "It's not possible to save changes. Possible reasons include:\n- your browser doesn't support saving (Firefox, Internet Explorer, Safari and Opera all work if properly configured)\n- the pathname to your TiddlyWiki file contains illegal characters\n- the TiddlyWiki HTML file has been moved or renamed",
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to save backup file",
	rssSaved: "RSS feed saved",
	rssFailed: "Failed to save RSS feed file",
	emptySaved: "Empty template saved",
	emptyFailed: "Failed to save empty template file",
	mainSaved: "Main TiddlyWiki file saved",
	mainFailed: "Failed to save main TiddlyWiki file. Your changes have not been saved",
	macroError: "Error in macro >",
	macroErrorDetails: "Error while executing macro >:\n%1",
	missingMacro: "No such macro",
	overwriteWarning: "A tiddler named '%0' already exists. Choose OK to overwrite it",
	unsavedChangesWarning: "WARNING! There are unsaved changes in TiddlyWiki\n\nChoose OK to save\nChoose CANCEL to discard",
	confirmExit: "--------------------------------\n\nThere are unsaved changes in TiddlyWiki. If you continue you will lose those changes\n\n--------------------------------",
	saveInstructions: "SaveChanges",
	unsupportedTWFormat: "Unsupported TiddlyWiki format '%0'",
	tiddlerSaveError: "Error when saving tiddler '%0'",
	tiddlerLoadError: "Error when loading tiddler '%0'",
	wrongSaveFormat: "Cannot save with storage format '%0'. Using standard format for save.",
	invalidFieldName: "Invalid field name %0",
	fieldCannotBeChanged: "Field '%0' cannot be changed",
	loadingMissingTiddler: "Attempting to retrieve the tiddler '%0' from the '%1' server at:\n\n'%2' in the workspace '%3'",
	upgradeDone: "The upgrade to version %0 is now complete\n\nClick 'OK' to reload the newly upgraded TiddlyWiki",
	invalidCookie: "Invalid cookie '%0'"});

merge(config.messages.messageClose,{
	text: "close",
	tooltip: "close this message area"});

config.messages.backstage = {
	open: {text: "backstage", tooltip: "Open the backstage area to perform authoring and editing tasks"},
	close: {text: "close", tooltip: "Close the backstage area"},
	prompt: "backstage: ",
	decal: {
		edit: {text: "edit", tooltip: "Edit the tiddler '%0'"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "Click for the full text of this tiddler",
	previewUnavailable: "(preview not available)"
};

config.messages.dates.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"];
config.messages.dates.days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
		"th","th","th","th","th","th","th","th","th","th",
		"st","nd","rd","th","th","th","th","th","th","th",
		"st"];
config.messages.dates.am = "am";
config.messages.dates.pm = "pm";

merge(config.messages.tiddlerPopup,{
	});

merge(config.views.wikified.tag,{
	labelNoTags: "no tags",
	labelTags: "tags: ",
	openTag: "Open tag '%0'",
	tooltip: "Show tiddlers tagged with '%0'",
	openAllText: "Open all",
	openAllTooltip: "Open all of these tiddlers",
	popupNone: "No other tiddlers tagged with '%0'"});

merge(config.views.wikified,{
	defaultText: "The tiddler '%0' doesn't yet exist. Double-click to create it",
	defaultModifier: "(missing)",
	shadowModifier: "(built-in shadow tiddler)",
	dateFormat: "DD MMM YYYY",
	createdPrompt: "created"});

merge(config.views.editor,{
	tagPrompt: "Type tags separated with spaces, [[use double square brackets]] if necessary, or add existing",
	defaultText: "Type the text for '%0'"});

merge(config.views.editor.tagChooser,{
	text: "tags",
	tooltip: "Choose existing tags to add to this tiddler",
	popupNone: "There are no tags defined",
	tagTooltip: "Add the tag '%0'"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: "search",
	prompt: "Search this TiddlyWiki",
	placeholder: "",
	accessKey: "F",
	successMsg: "%0 tiddlers found matching %1",
	failureMsg: "No tiddlers found matching %0"});

merge(config.macros.tagging,{
	label: "tagging: ",
	labelNotTag: "not tagging",
	tooltip: "List of tiddlers tagged with '%0'"});

merge(config.macros.timeline,{
	dateFormat: "DD MMM YYYY"});

merge(config.macros.allTags,{
	tooltip: "Show tiddlers tagged with '%0'",
	noTags: "There are no tagged tiddlers"});

config.macros.list.all.prompt = "All tiddlers in alphabetical order";
config.macros.list.missing.prompt = "Tiddlers that have links to them but are not defined";
config.macros.list.orphans.prompt = "Tiddlers that are not linked to from any other tiddlers";
config.macros.list.shadowed.prompt = "Tiddlers shadowed with default contents";
config.macros.list.touched.prompt = "Tiddlers that have been modified locally";

merge(config.macros.closeAll,{
	label: "close all",
	prompt: "Close all displayed tiddlers (except any that are being edited)"});

merge(config.macros.permaview,{
	label: "permaview",
	prompt: "Link to an URL that retrieves all the currently displayed tiddlers"});

merge(config.macros.saveChanges,{
	label: "save changes",
	prompt: "Save all tiddlers to create a new TiddlyWiki",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "new tiddler",
	prompt: "Create a new tiddler",
	title: "New Tiddler",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "new journal",
	prompt: "Create a new tiddler from the current date and time",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "Tweak advanced options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "
Show unknown options", unknownDescription: "//(unknown)//", listViewTemplate: { columns: [ {name: 'Option', field: 'option', title: "Option", type: 'String'}, {name: 'Description', field: 'description', title: "Description", type: 'WikiText'}, {name: 'Name', field: 'name', title: "Name", type: 'String'} ], rowClasses: [ {className: 'lowlight', field: 'lowlight'} ]} }); merge(config.macros.plugins,{ wizardTitle: "Manage plugins", step1Title: "Currently loaded plugins", step1Html: "", // DO NOT TRANSLATE skippedText: "(This plugin has not been executed because it was added since startup)", noPluginText: "There are no plugins installed", confirmDeleteText: "Are you sure you want to delete these plugins:\n\n%0", removeLabel: "remove systemConfig tag", removePrompt: "Remove systemConfig tag", deleteLabel: "delete", deletePrompt: "Delete these tiddlers forever", listViewTemplate: { columns: [ {name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'}, {name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'}, {name: 'Description', field: 'Description', title: "Description", type: 'String'}, {name: 'Version', field: 'Version', title: "Version", type: 'String'}, {name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'}, {name: 'Forced', field: 'forced', title: "Forced", tag: 'systemConfigForce', type: 'TagCheckbox'}, {name: 'Disabled', field: 'disabled', title: "Disabled", tag: 'systemConfigDisable', type: 'TagCheckbox'}, {name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"}, {name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'}, {name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"}, {name: 'Log', field: 'log', title: "Log", type: 'StringList'} ], rowClasses: [ {className: 'error', field: 'error'}, {className: 'warning', field: 'warning'} ]}, listViewTemplateReadOnly: { columns: [ {name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'}, {name: 'Description', field: 'Description', title: "Description", type: 'String'}, {name: 'Version', field: 'Version', title: "Version", type: 'String'}, {name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'}, {name: 'Executed', field: 'executed', title: "Loaded", type: 'Boolean', trueText: "Yes", falseText: "No"}, {name: 'Startup Time', field: 'startupTime', title: "Startup Time", type: 'String'}, {name: 'Error', field: 'error', title: "Status", type: 'Boolean', trueText: "Error", falseText: "OK"}, {name: 'Log', field: 'log', title: "Log", type: 'StringList'} ], rowClasses: [ {className: 'error', field: 'error'}, {className: 'warning', field: 'warning'} ]} }); merge(config.macros.toolbar,{ moreLabel: "more", morePrompt: "Show additional commands", lessLabel: "less", lessPrompt: "Hide additional commands", separator: "|" }); merge(config.macros.refreshDisplay,{ label: "refresh", prompt: "Redraw the entire TiddlyWiki display" }); merge(config.macros.importTiddlers,{ readOnlyWarning: "You cannot import into a read-only TiddlyWiki file. Try opening it from a file:// URL", wizardTitle: "Import tiddlers from another file or server", step1Title: "Step 1: Locate the server or TiddlyWiki file", step1Html: "Specify the type of the server:
Enter the URL or pathname here:
...or browse for a file:

...or select a pre-defined feed: ", openLabel: "open", openPrompt: "Open the connection to this file or server", statusOpenHost: "Opening the host", statusGetWorkspaceList: "Getting the list of available workspaces", step2Title: "Step 2: Choose the workspace", step2Html: "Enter a workspace name:
...or select a workspace: ", cancelLabel: "cancel", cancelPrompt: "Cancel this import", statusOpenWorkspace: "Opening the workspace", statusGetTiddlerList: "Getting the list of available tiddlers", errorGettingTiddlerList: "Error getting list of tiddlers, click Cancel to try again", errorGettingTiddlerListHttp404: "Error retrieving tiddlers from url, please ensure the url exists. Click Cancel to try again.", errorGettingTiddlerListHttp: "Error retrieving tiddlers from url, please ensure this url exists and is CORS enabled", errorGettingTiddlerListFile: "Error retrieving tiddlers from local file, please make sure the file is in the same directory as your TiddlyWiki. Click Cancel to try again.", step3Title: "Step 3: Choose the tiddlers to import", step3Html: "
Keep these tiddlers linked to this server so that you can synchronise subsequent changes
Save the details of this server in a 'systemServer' tiddler called: ", importLabel: "import", importPrompt: "Import these tiddlers", confirmOverwriteText: "Are you sure you want to overwrite these tiddlers:\n\n%0", step4Title: "Step 4: Importing %0 tiddler(s)", step4Html: "", // DO NOT TRANSLATE doneLabel: "done", donePrompt: "Close this wizard", statusDoingImport: "Importing tiddlers", statusDoneImport: "All tiddlers imported", systemServerNamePattern: "%2 on %1", systemServerNamePatternNoWorkspace: "%1", confirmOverwriteSaveTiddler: "The tiddler '%0' already exists. Click 'OK' to overwrite it with the details of this server, or 'Cancel' to leave it unchanged", serverSaveTemplate: "|''Type:''|%0|\n|''URL:''|%1|\n|''Workspace:''|%2|\n\nThis tiddler was automatically created to record the details of this server", serverSaveModifier: "(System)", listViewTemplate: { columns: [ {name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'}, {name: 'Tiddler', field: 'tiddler', title: "Tiddler", type: 'Tiddler'}, {name: 'Size', field: 'size', tiddlerLink: 'size', title: "Size", type: 'Size'}, {name: 'Tags', field: 'tags', title: "Tags", type: 'Tags'} ], rowClasses: [ ]} }); merge(config.macros.upgrade,{ wizardTitle: "Upgrade TiddlyWiki core code", step1Title: "Update or repair this TiddlyWiki to the latest release", step1Html: "You are about to upgrade to the latest release of the TiddlyWiki core code (from %1). Your content will be preserved across the upgrade.

Note that core upgrades have been known to interfere with older plugins. If you run into problems with the upgraded file, see http://www.tiddlywiki.org/wiki/CoreUpgrades", errorCantUpgrade: "Unable to upgrade this TiddlyWiki. You can only perform upgrades on TiddlyWiki files stored locally", errorNotSaved: "You must save changes before you can perform an upgrade", step2Title: "Confirm the upgrade details", step2Html_downgrade: "You are about to downgrade to TiddlyWiki version %0 from %1.

Downgrading to an earlier version of the core code is not recommended", step2Html_restore: "This TiddlyWiki appears to be already using the latest version of the core code (%0).

You can continue to upgrade anyway to ensure that the core code hasn't been corrupted or damaged", step2Html_upgrade: "You are about to upgrade to TiddlyWiki version %0 from %1", upgradeLabel: "upgrade", upgradePrompt: "Prepare for the upgrade process", statusPreparingBackup: "Preparing backup", statusSavingBackup: "Saving backup file", errorSavingBackup: "There was a problem saving the backup file", statusLoadingCore: "Loading core code", errorLoadingCore: "Error loading the core code", errorCoreFormat: "Error with the new core code", statusSavingCore: "Saving the new core code", statusReloadingCore: "Reloading the new core code", startLabel: "start", startPrompt: "Start the upgrade process", cancelLabel: "cancel", cancelPrompt: "Cancel the upgrade process", step3Title: "Upgrade cancelled", step3Html: "You have cancelled the upgrade process" }); merge(config.macros.annotations,{ }); merge(config.commands.closeTiddler,{ text: "close", tooltip: "Close this tiddler"}); merge(config.commands.closeOthers,{ text: "close others", tooltip: "Close all other tiddlers"}); merge(config.commands.editTiddler,{ text: "edit", tooltip: "Edit this tiddler", readOnlyText: "view", readOnlyTooltip: "View the source of this tiddler"}); merge(config.commands.saveTiddler,{ text: "done", tooltip: "Save changes to this tiddler"}); merge(config.commands.cancelTiddler,{ text: "cancel", tooltip: "Undo changes to this tiddler", warning: "Are you sure you want to abandon your changes to '%0'?", readOnlyText: "done", readOnlyTooltip: "View this tiddler normally"}); merge(config.commands.deleteTiddler,{ text: "delete", tooltip: "Delete this tiddler", warning: "Are you sure you want to delete '%0'?"}); merge(config.commands.permalink,{ text: "permalink", tooltip: "Permalink for this tiddler"}); merge(config.commands.references,{ text: "references", tooltip: "Show tiddlers that link to this one", popupNone: "No references"}); merge(config.commands.jump,{ text: "jump", tooltip: "Jump to another open tiddler"}); merge(config.commands.fields,{ text: "fields", tooltip: "Show the extended fields of this tiddler", emptyText: "There are no extended fields for this tiddler", listViewTemplate: { columns: [ {name: 'Field', field: 'field', title: "Field", type: 'String'}, {name: 'Value', field: 'value', title: "Value", type: 'String'} ], rowClasses: [ ], buttons: [ ]}}); merge(config.shadowTiddlers,{ DefaultTiddlers: "[[GettingStarted]]", MainMenu: "[[GettingStarted]]", SiteTitle: "My TiddlyWiki", SiteSubtitle: "a reusable non-linear personal web notebook", SiteUrl: "", SideBarOptions: '>>>>>>>', SideBarTabs: '>', TabMore: '>' }); merge(config.annotations,{ AdvancedOptions: "This shadow tiddler provides access to several advanced options", ColorPalette: "These values in this shadow tiddler determine the colour scheme of the ~TiddlyWiki user interface", DefaultTiddlers: "The tiddlers listed in this shadow tiddler will be automatically displayed when ~TiddlyWiki starts up", EditTemplate: "The HTML template in this shadow tiddler determines how tiddlers look while they are being edited", GettingStarted: "This shadow tiddler provides basic usage instructions", ImportTiddlers: "This shadow tiddler provides access to importing tiddlers", MainMenu: "This shadow tiddler is used as the contents of the main menu in the left-hand column of the screen", MarkupPreHead: "This tiddler is inserted at the top of the section of the TiddlyWiki HTML file", MarkupPostHead: "This tiddler is inserted at the bottom of the section of the TiddlyWiki HTML file", MarkupPreBody: "This tiddler is inserted at the top of the section of the TiddlyWiki HTML file", MarkupPostBody: "This tiddler is inserted at the end of the section of the TiddlyWiki HTML file immediately after the script block", OptionsPanel: "This shadow tiddler is used as the contents of the options panel slider in the right-hand sidebar", PageTemplate: "The HTML template in this shadow tiddler determines the overall ~TiddlyWiki layout", PluginManager: "This shadow tiddler provides access to the plugin manager", SideBarOptions: "This shadow tiddler is used as the contents of the option panel in the right-hand sidebar", SideBarTabs: "This shadow tiddler is used as the contents of the tabs panel in the right-hand sidebar", SiteSubtitle: "This shadow tiddler is used as the second part of the page title", SiteTitle: "This shadow tiddler is used as the first part of the page title", SiteUrl: "This shadow tiddler should be set to the full target URL for publication", StyleSheetColors: "This shadow tiddler contains CSS definitions related to the color of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler", StyleSheet: "This tiddler can contain custom CSS definitions", StyleSheetLayout: "This shadow tiddler contains CSS definitions related to the layout of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler", StyleSheetLocale: "This shadow tiddler contains CSS definitions related to the translation locale", StyleSheetPrint: "This shadow tiddler contains CSS definitions for printing", SystemSettings: "This tiddler is used to store configuration options for this TiddlyWiki document", TabAll: "This shadow tiddler contains the contents of the 'All' tab in the right-hand sidebar", TabMore: "This shadow tiddler contains the contents of the 'More' tab in the right-hand sidebar", TabMoreMissing: "This shadow tiddler contains the contents of the 'Missing' tab in the right-hand sidebar", TabMoreOrphans: "This shadow tiddler contains the contents of the 'Orphans' tab in the right-hand sidebar", TabMoreShadowed: "This shadow tiddler contains the contents of the 'Shadowed' tab in the right-hand sidebar", TabTags: "This shadow tiddler contains the contents of the 'Tags' tab in the right-hand sidebar", TabTimeline: "This shadow tiddler contains the contents of the 'Timeline' tab in the right-hand sidebar", ToolbarCommands: "This shadow tiddler determines which commands are shown in tiddler toolbars", ViewTemplate: "The HTML template in this shadow tiddler determines how tiddlers look" }); //-- //-- Paramifiers //-- function getParameters() { var p = null; if(window.location.hash) { p = decodeURIComponent(window.location.hash.substr(1)); if(config.browser.firefoxDate != null && config.browser.firefoxDate[1] 1) { last.element.setAttribute("colspan",colSpanCount); last.element.setAttribute("colSpan",colSpanCount); // Needed for IE colSpanCount = 1; } } w.nextMatch = this.cellRegExp.lastIndex-1; } else if(cellMatch[1] == ">") { // Colspan colSpanCount++; w.nextMatch = this.cellRegExp.lastIndex-1; } else if(cellMatch[2]) { // End of row if(prevCell && colSpanCount > 1) { prevCell.setAttribute("colspan",colSpanCount); prevCell.setAttribute("colSpan",colSpanCount); // Needed for IE } w.nextMatch = this.cellRegExp.lastIndex; break; } else { // Cell w.nextMatch++; var styles = config.formatterHelpers.inlineCssHelper(w); var spaceLeft = false; var chr = w.source.substr(w.nextMatch,1); while(chr == " ") { spaceLeft = true; w.nextMatch++; chr = w.source.substr(w.nextMatch,1); } var cell; if(chr == "!") { cell = createTiddlyElement(e,"th"); w.nextMatch++; } else { cell = createTiddlyElement(e,"td"); } prevCell = cell; prevColumns[col] = {rowSpanCount:1,element:cell}; if(colSpanCount > 1) { cell.setAttribute("colspan",colSpanCount); cell.setAttribute("colSpan",colSpanCount); // Needed for IE colSpanCount = 1; } config.formatterHelpers.applyCssHelper(cell,styles); w.subWikifyTerm(cell,this.cellTermRegExp); if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight cell.align = spaceLeft ? "center" : "left"; else if(spaceLeft) cell.align = "right"; w.nextMatch--; } col++; this.cellRegExp.lastIndex = w.nextMatch; cellMatch = this.cellRegExp.exec(w.source); } } }, { name: "heading", match: "^!{1,6}", termRegExp: /(\n)/mg, handler: function(w) { w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength),this.termRegExp); } }, { name: "list", match: "^(?:[\\*#;:]+)", lookaheadRegExp: /^(?:(?:(\*)|(#)|(;)|(:))+)/mg, termRegExp: /(\n)/mg, handler: function(w) { var stack = [w.output]; var currLevel = 0, currType = null; var listLevel, listType, itemType, baseType; w.nextMatch = w.matchStart; this.lookaheadRegExp.lastIndex = w.nextMatch; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) { if(lookaheadMatch[1]) { listType = "ul"; itemType = "li"; } else if(lookaheadMatch[2]) { listType = "ol"; itemType = "li"; } else if(lookaheadMatch[3]) { listType = "dl"; itemType = "dt"; } else if(lookaheadMatch[4]) { listType = "dl"; itemType = "dd"; } if(!baseType) baseType = listType; listLevel = lookaheadMatch[0].length; w.nextMatch += lookaheadMatch[0].length; var t; if(listLevel > currLevel) { for(t=currLevel; tlistLevel; t--) stack.pop(); } else if(listLevel == currLevel && listType != currType) { stack.pop(); stack.push(createTiddlyElement(stack[stack.length-1].lastChild,listType)); } currLevel = listLevel; currType = listType; var e = createTiddlyElement(stack[stack.length-1],itemType); w.subWikifyTerm(e,this.termRegExp); this.lookaheadRegExp.lastIndex = w.nextMatch; lookaheadMatch = this.lookaheadRegExp.exec(w.source); } } }, { name: "quoteByBlock", match: "^+", lookaheadRegExp: /^>+/mg, termRegExp: /(\n)/mg, element: "blockquote", handler: function(w) { var stack = [w.output]; var currLevel = 0; var newLevel = w.matchLength; var t,matched; do { if(newLevel > currLevel) { for(t=currLevel; tnewLevel; t--) stack.pop(); } currLevel = newLevel; w.subWikifyTerm(stack[stack.length-1],this.termRegExp); createTiddlyElement(stack[stack.length-1],"br"); this.lookaheadRegExp.lastIndex = w.nextMatch; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch; if(matched) { newLevel = lookaheadMatch[0].length; w.nextMatch += lookaheadMatch[0].length; } } while(matched); } }, { name: "rule", match: "^----+$\\n?|
\\n?", handler: function(w) { createTiddlyElement(w.output,"hr"); } }, { name: "monospacedByLine", match: "^(?:/\\*\\{\\{\\{\\*/|\\{\\{\\{|//\\{\\{\\{|)\\n", element: "pre", handler: function(w) { switch(w.matchText) { case "/*{{{*/\n": // CSS this.lookaheadRegExp = /\/\*\{\{\{\*\/\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\*\}\}\}\*\/$\n?)/mg; break; case "{{{\n": // monospaced block this.lookaheadRegExp = /^\{\{\{\n((?:^[^\n]*\n)+?)(^\f*\}\}\}$\n?)/mg; break; case "//{{{\n": // plugin this.lookaheadRegExp = /^\/\/\{\{\{\n\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\/\}\}\}$\n?)/mg; break; case "\n": //template this.lookaheadRegExp = /\n*((?:^[^\n]*\n)+?)(\n*^\f*$\n?)/mg; break; default: break; } config.formatterHelpers.enclosedTextHelper.call(this,w); } }, { name: "wikifyComment", match: "^(?:/\\*\\*\\*|\n)/mg); w.subWikifyTerm(w.output,termRegExp); } }, { name: "macro", match: "\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) { w.nextMatch = this.lookaheadRegExp.lastIndex; invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler); } } }, { name: "prettyLink", match: "\\[\\[", lookaheadRegExp: /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { var e; var text = lookaheadMatch[1]; if(lookaheadMatch[3]) { // Pretty bracketted link var link = lookaheadMatch[3]; e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link)) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler); } else { // Simple bracketted link e = createTiddlyLink(w.output,text,false,null,w.isStatic,w.tiddler); } createTiddlyText(e,text); w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "wikiLink", match: config.textPrimitives.unWikiLink+"?"+config.textPrimitives.wikiLink, handler: function(w) { if(w.matchText.substr(0,1) == config.textPrimitives.unWikiLink) { w.outputText(w.output,w.matchStart+1,w.nextMatch); return; } if(w.matchStart > 0) { var preRegExp = new RegExp(config.textPrimitives.anyLetterStrict,"mg"); preRegExp.lastIndex = w.matchStart-1; var preMatch = preRegExp.exec(w.source); if(preMatch.index == w.matchStart-1) { w.outputText(w.output,w.matchStart,w.nextMatch); return; } } if(w.autoLinkWikiWords || store.isShadowTiddler(w.matchText)) { var link = createTiddlyLink(w.output,w.matchText,false,null,w.isStatic,w.tiddler); w.outputText(link,w.matchStart,w.nextMatch); } else { w.outputText(w.output,w.matchStart,w.nextMatch); } } }, { name: "urlLink", match: config.textPrimitives.urlPattern, handler: function(w) { w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch); } }, { name: "image", match: "\\[[]?[Ii][Mm][Gg]\\[", lookaheadRegExp: /\[([?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { var e = w.output; if(lookaheadMatch[5]) { var link = lookaheadMatch[5]; e = config.formatterHelpers.isExternalLink(link) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler); jQuery(e).addClass("imageLink"); } var img = createTiddlyElement(e,"img"); if(lookaheadMatch[1]) img.align = "left"; else if(lookaheadMatch[2]) img.align = "right"; if(lookaheadMatch[3]) { img.title = lookaheadMatch[3]; img.setAttribute("alt",lookaheadMatch[3]); } img.src = lookaheadMatch[4]; w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "html", match: "", lookaheadRegExp: /((?:.|\n)*?)/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1]; w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "commentByBlock", match: "/%", lookaheadRegExp: /\/%((?:.|\n)*?)%\//mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) w.nextMatch = this.lookaheadRegExp.lastIndex; } }, { name: "characterFormat", match: "''|//|__|\\^\\^|~~|--(?!\\s|$)|\\{\\{\\{", handler: function(w) { switch(w.matchText) { case "''": w.subWikifyTerm(w.output.appendChild(document.createElement("strong")),/('')/mg); break; case "//": w.subWikifyTerm(createTiddlyElement(w.output,"em"),/(\/\/)/mg); break; case "__": w.subWikifyTerm(createTiddlyElement(w.output,"u"),/(__)/mg); break; case "^^": w.subWikifyTerm(createTiddlyElement(w.output,"sup"),/(\^\^)/mg); break; case "~~": w.subWikifyTerm(createTiddlyElement(w.output,"sub"),/(~~)/mg); break; case "--": w.subWikifyTerm(createTiddlyElement(w.output,"strike"),/(--)/mg); break; case "{{{": var lookaheadRegExp = /\{\{\{((?:.|\n)*?)\}\}\}/mg; lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]); w.nextMatch = lookaheadRegExp.lastIndex; } break; } } }, { name: "customFormat", match: "@@|\\{\\{", handler: function(w) { switch(w.matchText) { case "@@": var e = createTiddlyElement(w.output,"span"); var styles = config.formatterHelpers.inlineCssHelper(w); if(styles.length == 0) e.className = "marked"; else config.formatterHelpers.applyCssHelper(e,styles); w.subWikifyTerm(e,/(@@)/mg); break; case "{{": var lookaheadRegExp = /\{\{[\s]*([\w]+[\s\w]*)[\s]*\{(\n?)/mg; lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = lookaheadRegExp.exec(w.source); if(lookaheadMatch) { w.nextMatch = lookaheadRegExp.lastIndex; e = createTiddlyElement(w.output,lookaheadMatch[2] == "\n" ? "div" : "span",null,lookaheadMatch[1]); w.subWikifyTerm(e,/(\}\}\})/mg); } break; } } }, { name: "mdash", match: "--", handler: function(w) { createTiddlyElement(w.output,"span").innerHTML = "—"; } }, { name: "lineBreak", match: "\\n|
", handler: function(w) { createTiddlyElement(w.output,"br"); } }, { name: "rawText", match: "\"{3}|", lookaheadRegExp: /(?:\"{3}|)((?:.|\n)*?)(?:\"{3}|)/mg, handler: function(w) { this.lookaheadRegExp.lastIndex = w.matchStart; var lookaheadMatch = this.lookaheadRegExp.exec(w.source); if(lookaheadMatch && lookaheadMatch.index == w.matchStart) { createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]); w.nextMatch = this.lookaheadRegExp.lastIndex; } } }, { name: "htmlEntitiesEncoding", match: "(?:(?:?[a-zA-Z0-9]{2,8};|.)(?:?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|?[a-zA-Z0-9]{2,8};)", handler: function(w) { createTiddlyElement(w.output,"span").innerHTML = w.matchText; } } ]; //-- //-- Wikifier //-- function getParser(tiddler,format) { if(tiddler) { if(!format) format = tiddler.fields["wikiformat"]; var i; if(format) { for(i in config.parsers) { if(format == config.parsers[i].format) return config.parsers[i]; } } else { for(i in config.parsers) { if(tiddler.isTagged(config.parsers[i].formatTag)) return config.parsers[i]; } } } return formatter; } function Wikifier(source,formatter,highlightRegExp,tiddler) { this.source = source; this.output = null; this.formatter = formatter; this.nextMatch = 0; this.autoLinkWikiWords = tiddler && tiddler.autoLinkWikiWords() == false ? false : true; this.highlightRegExp = highlightRegExp; this.highlightMatch = null; this.isStatic = false; if(highlightRegExp) { highlightRegExp.lastIndex = 0; this.highlightMatch = highlightRegExp.exec(source); } this.tiddler = tiddler; } Wikifier.prototype.wikifyPlain = function() { var e = createTiddlyElement(document.body,"div"); e.style.display = "none"; this.subWikify(e); var text = jQuery(e).text(); jQuery(e).remove(); return text; }; Wikifier.prototype.subWikify = function(output,terminator) { try { if(terminator) this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg")); else this.subWikifyUnterm(output); } catch(ex) { showException(ex); } }; Wikifier.prototype.subWikifyUnterm = function(output) { var oldOutput = this.output; this.output = output; this.formatter.formatterRegExp.lastIndex = this.nextMatch; var formatterMatch = this.formatter.formatterRegExp.exec(this.source); while(formatterMatch) { // Output any text before the match if(formatterMatch.index > this.nextMatch) this.outputText(this.output,this.nextMatch,formatterMatch.index); // Set the match parameters for the handler this.matchStart = formatterMatch.index; this.matchLength = formatterMatch[0].length; this.matchText = formatterMatch[0]; this.nextMatch = this.formatter.formatterRegExp.lastIndex; var t; for(t=1; t this.nextMatch) this.outputText(this.output,this.nextMatch,terminatorMatch.index); this.matchText = terminatorMatch[1]; this.matchLength = terminatorMatch[1].length; this.matchStart = terminatorMatch.index; this.nextMatch = this.matchStart + this.matchLength; this.output = oldOutput; return; } if(formatterMatch.index > this.nextMatch) this.outputText(this.output,this.nextMatch,formatterMatch.index); this.matchStart = formatterMatch.index; this.matchLength = formatterMatch[0].length; this.matchText = formatterMatch[0]; this.nextMatch = this.formatter.formatterRegExp.lastIndex; var t; for(t=1; t startPos) && (this.highlightMatch.index startPos) { createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index)); startPos = this.highlightMatch.index; } var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos); createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd)); startPos = highlightEnd; if(startPos >= this.highlightRegExp.lastIndex) this.highlightMatch = this.highlightRegExp.exec(this.source); } if(startPos 0) text = text.substr(0,limit); var wikifier = new Wikifier(text,formatter,null,tiddler); return wikifier.wikifyPlain(); } function highlightify(source,output,highlightRegExp,tiddler) { if(source) { var wikifier = new Wikifier(source,formatter,highlightRegExp,tiddler); wikifier.outputText(output,0,source.length); } } //-- //-- Macro definitions //-- function invokeMacro(place,macro,params,wikifier,tiddler) { try { var m = config.macros[macro]; if(m && m.handler) { var tiddlerElem = story.findContainingTiddler(place); window.tiddler = tiddlerElem ? store.getTiddler(tiddlerElem.getAttribute("tiddler")) : null; window.place = place; var allowEval = true; if(config.evaluateMacroParameters=="system") { if(!tiddler || tiddler.tags.indexOf("systemAllowEval") == -1) { allowEval = false; } } m.handler(place,macro,m.noPreParse?null:params.readMacroParams(!allowEval),wikifier,params,tiddler); } else { createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,config.messages.missingMacro])); } } catch(ex) { createTiddlyError(place,config.messages.macroError.format([macro]),config.messages.macroErrorDetails.format([macro,ex.toString()])); } } config.macros.version.handler = function(place) { jQuery("").text(formatVersion()).appendTo(place); }; config.macros.today.handler = function(place,macroName,params) { var now = new Date(); var text = params[0] ? now.formatString(params[0].trim()) : now.toLocaleString(); jQuery("").text(text).appendTo(place); }; config.macros.list.template = ">"; config.macros.list.handler = function(place,macroName,params,wikifier,paramString) { var list = document.createElement("ul"); jQuery(list).attr({ refresh: "macro", macroName: macroName }).data("params", paramString); place.appendChild(list); this.refresh(list); }; config.macros.list.refresh = function(list) { var paramString = jQuery(list).data("params"); var params = paramString.readMacroParams(); var args = paramString.parseParams("anon", null, null)[0]; var type = args.anon ? args.anon[0] : "all"; jQuery(list).empty().addClass("list list-" + type); var template = args.template ? store.getTiddlerText(args.template[0]) : false; if(!template) { template = config.macros.list.template; } if(this[type].prompt) createTiddlyElement(list,"li",null,"listTitle",this[type].prompt); var results; if(this[type].handler) results = this[type].handler(params); var t; for(t = 0; t ").text(args.emptyMessage[0]).appendTo(list); } }; config.macros.list.all.handler = function(params) { return store.reverseLookup("tags","excludeLists",false,"title"); }; config.macros.list.missing.handler = function(params) { return store.getMissingLinks(); }; config.macros.list.orphans.handler = function(params) { return store.getOrphans(); }; config.macros.list.shadowed.handler = function(params) { return store.getShadowed(); }; config.macros.list.touched.handler = function(params) { return store.getTouched(); }; config.macros.list.filter.handler = function(params) { var filter = params[1]; var results = []; if(filter) { var tiddlers = store.filterTiddlers(filter); var t; for(t=0; t").attr("params", paramString). attr("macroName", macroName).appendTo(place)[0]; macro.refresh(container); }, refresh: function(container) { jQuery(container).attr("refresh", "macro").empty(); var paramString = jQuery(container).attr("params"); var args = paramString.parseParams("anon", null, null)[0]; var params = args.anon || []; var field = params[0] || "modified"; var prefix = field.charAt(0); var no_prefix_field = prefix === "-" || prefix === "+" ? field.substr(1, field.length) : field; var dateFormat = params[2] || this.dateFormat; var groupTemplate = macro.groupTemplate.format(no_prefix_field, dateFormat); groupTemplate = args.groupTemplate ? store.getTiddlerText(args.groupTemplate[0]) || groupTemplate : groupTemplate; var itemTemplate = macro.itemTemplate; itemTemplate = args.template ? store.getTiddlerText(args.template[0]) || itemTemplate : itemTemplate; var tiddlers = args.filter ? store.sortTiddlers(store.filterTiddlers(args.filter[0]), field) : store.reverseLookup("tags", "excludeLists", false, field); var lastGroup = "", ul; var last = params[1] ? tiddlers.length-Math.min(tiddlers.length,parseInt(params[1],10)) : 0; var t; for(t=tiddlers.length-1; t>=last; t--) { var tiddler = tiddlers[t]; var theGroup = wikifyPlainText(groupTemplate,0,tiddler); if(typeof(ul) == "undefined" || theGroup != lastGroup) { ul = document.createElement("ul"); jQuery(ul).addClass("timeline"); container.appendChild(ul); createTiddlyElement(ul,"li",null,"listTitle",theGroup); lastGroup = theGroup; } var item = createTiddlyElement(ul,"li",null,"listLink"); wikify(itemTemplate,item,null,tiddler); } }, groupTemplate: ">", itemTemplate: ">" }); config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) { var allowEval = true; var stack = config.macros.tiddler.tiddlerStack; if(stack.length > 0 && config.evaluateMacroParameters == "system") { // included tiddler and "system" evaluation required, so check tiddler tagged appropriately var title = stack[stack.length-1]; var pos = title.indexOf(config.textPrimitives.sectionSeparator); if(pos != -1) { title = title.substr(0,pos); // get the base tiddler title } var t = store.getTiddler(title); if(!t || t.tags.indexOf("systemAllowEval") == -1) { allowEval = false; } } params = paramString.parseParams("name",null,allowEval,false,true); var names = params[0]["name"]; var tiddlerName = names[0]; var className = names[1] || null; var args = params[0]["with"]; var wrapper = createTiddlyElement(place,"span",null,className,null,{ refresh: "content", tiddler: tiddlerName }); if(args!==undefined) wrapper.setAttribute("args","[["+args.join("]] [[")+"]]"); this.transclude(wrapper,tiddlerName,args); }; config.macros.tiddler.transclude = function(wrapper,tiddlerName,args) { var text = store.getTiddlerText(tiddlerName); if(!text) return; var stack = config.macros.tiddler.tiddlerStack; if(stack.indexOf(tiddlerName) !== -1) return; stack.push(tiddlerName); try { if(typeof args == "string") args = args.readBracketedList(); var n = args ? Math.min(args.length,9) : 0; var i; for(i=0; i> config.macros.gradient.handler = function(place,macroName,params,wikifier,paramString,tiddler) { var panel = wikifier ? createTiddlyElement(place,"div",null,"gradient") : place; panel.style.position = "relative"; panel.style.overflow = "hidden"; panel.style.zIndex = "0"; if(wikifier) { var styles = config.formatterHelpers.inlineCssHelper(wikifier); config.formatterHelpers.applyCssHelper(panel,styles); } params = paramString.parseParams("color"); var locolors = [], hicolors = []; var t; for(t=2; t>"); if(document.all) { panel.style.height = "100%"; panel.style.width = "100%"; } }; config.macros.message.handler = function(place,macroName,params) { if(params[0]) { var names = params[0].split("."); var lookupMessage = function(root,nameIndex) { if(root[names[nameIndex]]) { if(nameIndex 50) return; if(config.macros.view.depth>0) { if (value==config.macros.view.values[config.macros.view.depth-1]) { return; } } config.macros.view.values[config.macros.view.depth] = value; config.macros.view.depth++; if(params[2]) value=params[2].unescapeLineBreaks().format([value]); wikify(value,place,highlightHack,tiddler); config.macros.view.depth--; config.macros.view.values[config.macros.view.depth] = null; }, date: function(value,place,params,wikifier,paramString,tiddler) { value = Date.convertFromYYYYMMDDHHMM(value); createTiddlyText(place,value.formatString(params[2] || config.views.wikified.dateFormat)); } }; config.macros.view.handler = function(place,macroName,params,wikifier,paramString,tiddler) { if((tiddler instanceof Tiddler) && params[0]) { var value = store.getValue(tiddler,params[0]); if(value) { var type = params[1] || config.macros.view.defaultView; var handler = config.macros.view.views[type]; if(handler) handler(value,place,params,wikifier,paramString,tiddler); } } }; config.macros.edit.handler = function(place,macroName,params,wikifier,paramString,tiddler) { var field = params[0]; var rows = params[1] || 0; var defVal = params[2] || ''; if((tiddler instanceof Tiddler) && field) { story.setDirty(tiddler.title,true); var e,v; if(field != "text" && !rows) { e = createTiddlyElement(null,"input",null,null,null,{ type: "text", edit: field, size: "40", autocomplete: "off" }); e.value = store.getValue(tiddler,field) || defVal; place.appendChild(e); } else { var wrapper1 = createTiddlyElement(null,"fieldset",null,"fieldsetFix"); var wrapper2 = createTiddlyElement(wrapper1,"div"); e = createTiddlyElement(wrapper2,"textarea"); e.value = v = store.getValue(tiddler,field) || defVal; rows = rows || 10; var lines = v.match(/\n/mg); var maxLines = Math.max(parseInt(config.options.txtMaxEditRows,10),5); if(lines != null && lines.length > rows) rows = lines.length + 5; rows = Math.min(rows,maxLines); e.setAttribute("rows",rows); e.setAttribute("edit",field); place.appendChild(wrapper1); } if(tiddler.isReadOnly()) { e.setAttribute("readOnly","readOnly"); jQuery(e).addClass("readOnly"); } return e; } }; config.macros.tagChooser.onClick = function(ev) { var e = ev || window.event; var lingo = config.views.editor.tagChooser; var popup = Popup.create(this); var tags = store.getTags(this.getAttribute("tags")); if(tags.length == 0) jQuery("
  • ").text(lingo.popupNone).appendTo(popup); var t; for(t=0; t 0) btn.setAttribute("params",tags.join("|")); btn.setAttribute("newFocus",newFocus); btn.setAttribute("newTemplate",getParam(params,"template",DEFAULT_EDIT_TEMPLATE)); if(customFields !== "") btn.setAttribute("customFields",customFields); var text = getParam(params,"text"); if(text !== undefined) btn.setAttribute("newText",text); return btn; }; config.macros.newTiddler.onClickNewTiddler = function() { var title = this.getAttribute("newTitle"); if(this.getAttribute("isJournal") == "true") { title = new Date().formatString(title.trim()); } var params = this.getAttribute("params"); var tags = params ? params.split("|") : []; var focus = this.getAttribute("newFocus"); var template = this.getAttribute("newTemplate"); var customFields = this.getAttribute("customFields"); if(!customFields && !store.isShadowTiddler(title)) customFields = String.encodeHashMap(config.defaultCustomFields); story.displayTiddler(null,title,template,false,null,null); var tiddlerElem = story.getTiddler(title); if(customFields) story.addCustomFields(tiddlerElem,customFields); var text = this.getAttribute("newText"); if(typeof text == "string" && story.getTiddlerField(title,"text")) story.getTiddlerField(title,"text").value = text.format([title]); var t; for(t=0;t 0) { story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch); txt.setAttribute("lastSearchText",txt.value); } }; config.macros.search.onClick = function(e) { config.macros.search.doSearch(this.nextSibling); return false; }; config.macros.search.onKeyPress = function(ev) { var me = config.macros.search; var e = ev || window.event; switch(e.keyCode) { case 9: // Tab return; case 13: // Ctrl-Enter case 10: // Ctrl-Enter on IE PC me.doSearch(this); break; case 27: // Escape this.value = ""; clearMessage(); break; } if(config.options.chkIncrementalSearch) { if(this.value.length > 2) { if(this.value != this.getAttribute("lastSearchText")) { if(me.timeout) { clearTimeout(me.timeout); } var txt = this; me.timeout = setTimeout(function() {me.doSearch(txt);},500); } } else { if(me.timeout) { clearTimeout(me.timeout); } } } }; config.macros.search.onFocus = function(e) { this.select(); }; //-- //-- Tabs macro //-- config.macros.tabs.handler = function(place,macroName,params) { var cookie = params[0]; var numTabs = (params.length-1)/3; var wrapper = createTiddlyElement(null,"div",null,"tabsetWrapper " + cookie); var tabset = createTiddlyElement(wrapper,"div",null,"tabset"); tabset.setAttribute("cookie",cookie); var validTab = false; var t; for(t=0; t": btn = createTiddlyButton(place,this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore); jQuery(btn).addClass("moreCommand"); var e = createTiddlyElement(place,"span",null,"moreCommand"); e.style.display = "none"; place = e; break; default: var className = ""; switch(c.substr(0,1)) { case "+": className = "defaultCommand"; c = c.substr(1); break; case "-": className = "cancelCommand"; c = c.substr(1); break; } if(config.commands[c]) { this.createCommand(place,c,tiddler,className); } else { this.customCommand(place,c,wikifier,tiddler); } break; } } }; // Overrideable function to extend toolbar handler config.macros.toolbar.customCommand = function(place,command,wikifier,tiddler) { }; //-- //-- Menu and toolbar commands //-- config.commands.closeTiddler.handler = function(event,src,title) { if(story.isDirty(title) && !readOnly) { if(!confirm(config.commands.cancelTiddler.warning.format([title]))) return false; } story.setDirty(title,false); story.closeTiddler(title,true); return false; }; config.commands.closeOthers.handler = function(event,src,title) { story.closeAllTiddlers(title); return false; }; config.commands.editTiddler.handler = function(event,src,title) { clearMessage(); var tiddlerElem = story.getTiddler(title); var fields = tiddlerElem.getAttribute("tiddlyFields"); story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE,false,null,fields); var e = story.getTiddlerField(title,config.options.txtEditorFocus||"text"); if(e) { setCaretPosition(e,0); } return false; }; config.commands.saveTiddler.handler = function(event,src,title) { var newTitle = story.saveTiddler(title,event.shiftKey); if(newTitle) story.displayTiddler(null,newTitle); return false; }; config.commands.cancelTiddler.handler = function(event,src,title) { if(story.hasChanges(title) && !readOnly) { if(!confirm(this.warning.format([title]))) return false; } story.setDirty(title,false); story.displayTiddler(null,title); return false; }; config.commands.deleteTiddler.handler = function(event,src,title) { var deleteIt = true; if(config.options.chkConfirmDelete) deleteIt = confirm(this.warning.format([title])); if(deleteIt) { store.removeTiddler(title); story.closeTiddler(title,true); autoSaveChanges(); } return false; }; config.commands.permalink.handler = function(event,src,title) { var t = encodeURIComponent(String.encodeTiddlyLink(title)); if(window.location.hash != t) window.location.hash = t; return false; }; config.commands.references.handlePopup = function(popup,title) { var references = store.getReferringTiddlers(title); var c = false; var r; for(r=0; r 0) ListView.create(popup,items,this.listViewTemplate); else createTiddlyElement(popup,"div",null,null,this.emptyText); }; //-- //-- Tiddler() object //-- function Tiddler(title) { this.title = title; this.text = ""; this.creator = null; this.modifier = null; this.created = new Date(); this.modified = this.created; this.links = []; this.linksUpdated = false; this.tags = []; this.fields = {}; return this; } Tiddler.prototype.getLinks = function() { if(this.linksUpdated==false) this.changed(); return this.links; }; // Returns the fields that are inherited in string field:"value" field2:"value2" format Tiddler.prototype.getInheritedFields = function() { var f = {}; var i; for(i in this.fields) { if(i=="server.host" || i=="server.workspace" || i=="wikiformat"|| i=="server.type") { f[i] = this.fields[i]; } } return String.encodeHashMap(f); }; // Increment the changeCount of a tiddler Tiddler.prototype.incChangeCount = function() { var c = this.fields['changecount']; c = c ? parseInt(c,10) : 0; this.fields['changecount'] = String(c+1); }; // Clear the changeCount of a tiddler Tiddler.prototype.clearChangeCount = function() { if(this.fields['changecount']) { delete this.fields['changecount']; } }; Tiddler.prototype.doNotSave = function() { return this.fields['doNotSave']; }; // Returns true if the tiddler has been updated since the tiddler was created or downloaded Tiddler.prototype.isTouched = function() { var changecount = this.fields.changecount || 0; return changecount > 0; }; // Change the text and other attributes of a tiddler Tiddler.prototype.set = function(title,text,modifier,modified,tags,created,fields,creator) { this.assign(title,text,modifier,modified,tags,created,fields,creator); this.changed(); return this; }; // Change the text and other attributes of a tiddler without triggered a tiddler.changed() call Tiddler.prototype.assign = function(title,text,modifier,modified,tags,created,fields,creator) { if(title != undefined) this.title = title; if(text != undefined) this.text = text; if(modifier != undefined) this.modifier = modifier; if(modified != undefined) this.modified = modified; if(creator != undefined) this.creator = creator; if(created != undefined) this.created = created; if(fields != undefined) this.fields = fields; if(tags != undefined) this.tags = (typeof tags == "string") ? tags.readBracketedList() : tags; else if(this.tags == undefined) this.tags = []; return this; }; // Get the tags for a tiddler as a string (space delimited, using [[brackets]] for tags containing spaces) Tiddler.prototype.getTags = function() { return String.encodeTiddlyLinkList(this.tags); }; // Test if a tiddler carries a tag Tiddler.prototype.isTagged = function(tag) { return this.tags.indexOf(tag) != -1; }; // Static method to convert "\n" to newlines, "\s" to "\" Tiddler.unescapeLineBreaks = function(text) { return text ? text.unescapeLineBreaks() : ""; }; // Convert newlines to "\n", "\" to "\s" Tiddler.prototype.escapeLineBreaks = function() { return this.text.escapeLineBreaks(); }; // Updates the secondary information (like links[] array) after a change to a tiddler Tiddler.prototype.changed = function() { this.links = []; var text = this.text; // remove 'quoted' text before scanning tiddler source text = text.replace(/\/%((?:.|\n)*?)%\//g,""). replace(/\{{3}((?:.|\n)*?)\}{3}/g,""). replace(/"""((?:.|\n)*?)"""/g,""). replace(/((?:.|\n)*?)/g,""). replace(/\>((?:.|\n)*?)/g,""). replace(/
  • \n" : tiddler.text.escapeLineBreaks().htmlEncode() ]); } catch (ex) { throw exceptionText(ex,config.messages.tiddlerSaveError.format([tiddler.title])); } }; /*** |''Name''|TiddlyWebAdaptor| |''Description''|adaptor for interacting with TiddlyWeb| |''Author:''|FND| |''Contributors''|Chris Dent, Martin Budden| |''Version''|1.4.10| |''Status''|stable| |''Source''|http://svn.tiddlywiki.org/Trunk/association/adaptors/TiddlyWebAdaptor.js| |''CodeRepository''|http://svn.tiddlywiki.org/Trunk/association/| |''License''|[[BSD|http://www.opensource.org/licenses/bsd-license.php]]| |''CoreVersion''|2.5| |''Keywords''|serverSide TiddlyWeb| !Notes This plugin includes [[jQuery JSON|http://code.google.com/p/jquery-json/]]. !To Do * createWorkspace * document custom/optional context attributes (e.g. filters, query, revision) and tiddler fields (e.g. server.title, origin) !Code ***/ //{{{ (function($) { var adaptor = config.adaptors.tiddlyweb = function() {}; adaptor.prototype = new AdaptorBase(); adaptor.serverType = "tiddlyweb"; adaptor.serverLabel = "TiddlyWeb"; adaptor.mimeType = "application/json"; adaptor.parsingErrorMessage = "Error parsing result from server"; adaptor.noBagErrorMessage = "no bag specified for tiddler"; adaptor.locationIDErrorMessage = "no bag or recipe specified for tiddler"; // TODO: rename // retrieve current status (requires TiddlyWeb status plugin) adaptor.prototype.getStatus = function(context, userParams, callback) { context = this.setContext(context, userParams, callback); var uriTemplate = "%0/status"; var uri = uriTemplate.format([context.host]); var req = httpReq("GET", uri, adaptor.getStatusCallback, context, null, null, null, null, null, true); return typeof req == "string" ? req : true; }; adaptor.getStatusCallback = function(status, context, responseText, uri, xhr) { context.status = responseText ? status : false; try { context.statusText = xhr.statusText; } catch(exc) { // offline (Firefox) context.status = false; context.statusText = null; } context.httpStatus = xhr.status; if(context.status) { context.serverStatus = $.evalJSON(responseText); // XXX: error handling!? } if(context.callback) { context.callback(context, context.userParams); } }; // retrieve a list of workspaces adaptor.prototype.getWorkspaceList = function(context, userParams, callback) { context = this.setContext(context, userParams, callback); context.workspaces = []; var uriTemplate = "%0/recipes"; // XXX: bags? var uri = uriTemplate.format([context.host]); var req = httpReq("GET", uri, adaptor.getWorkspaceListCallback, context, { accept: adaptor.mimeType }, null, null, null, null, true); return typeof req == "string" ? req : true; }; adaptor.getWorkspaceListCallback = function(status, context, responseText, uri, xhr) { context.status = status; context.statusText = xhr.statusText; context.httpStatus = xhr.status; if(status) { try { var workspaces = $.evalJSON(responseText); } catch(ex) { context.status = false; // XXX: correct? context.statusText = exceptionText(ex, adaptor.parsingErrorMessage); if(context.callback) { context.callback(context, context.userParams); } return; } context.workspaces = workspaces.map(function(itm) { return { title: itm }; }); } if(context.callback) { context.callback(context, context.userParams); } }; // retrieve a list of tiddlers adaptor.prototype.getTiddlerList = function(context, userParams, callback) { context = this.setContext(context, userParams, callback); var uriTemplate = "%0/%1/%2/tiddlers%3"; var params = context.filters ? "?" + context.filters : ""; if(context.format) { params = context.format + params; } var workspace = adaptor.resolveWorkspace(context.workspace); var uri = uriTemplate.format([context.host, workspace.type + "s", adaptor.normalizeTitle(workspace.name), params]); var req = httpReq("GET", uri, adaptor.getTiddlerListCallback, context, merge({ accept: adaptor.mimeType }, context.headers), null, null, null, null, true); return typeof req == "string" ? req : true; }; adaptor.getTiddlerListCallback = function(status, context, responseText, uri, xhr) { context.status = status; context.statusText = xhr.statusText; context.httpStatus = xhr.status; if(status) { context.tiddlers = []; try { var tiddlers = $.evalJSON(responseText); //# NB: not actual tiddler instances } catch(ex) { context.status = false; // XXX: correct? context.statusText = exceptionText(ex, adaptor.parsingErrorMessage); if(context.callback) { context.callback(context, context.userParams); } return; } for(var i = 0; i /" revisions[i].fields.origin = ["bags", revisions[i].bag, revisions[i].title].join("/"); } revisions[i].title = to.title; } // add new revision var rev = $.extend({}, revisions[0]); $.each(newTiddler, function(i, item) { if(!$.isFunction(item)) { rev[i] = item; } }); rev.title = to.title; rev.created = rev.created.convertToYYYYMMDDHHMM(); rev.modified = new Date().convertToYYYYMMDDHHMM(); delete rev.fields.changecount; revisions.unshift(rev); if(to.workspace) { context.workspace = to.workspace; } else if(context.workspace.substring(0, 4) != "bags") { // NB: target workspace must be a bag context.workspace = "bags/" + rev.bag; } var subCallback = function(context, userParams) { if(!context.status) { return callback(context, userParams); } context.adaptor.getTiddler(newTiddler.title, context, userParams, _deleteTiddler); }; return self.putTiddlerChronicle(revisions, context, context.userParams, subCallback); }; var _deleteTiddler = function(context, userParams) { if(!context.status) { return callback(context, userParams); } $.extend(true, newTiddler, context.tiddler); context.callback = null; return self.deleteTiddler(oldTiddler, context, context.userParams, callback); }; callback = callback || function() {}; context = this.setContext(context, userParams); context.host = context.host || oldTiddler.fields["server.host"]; context.workspace = from.workspace || oldTiddler.fields["server.workspace"]; return _getTiddlerChronicle(from.title, context, userParams, _putTiddlerChronicle); }; // delete an individual tiddler adaptor.prototype.deleteTiddler = function(tiddler, context, userParams, callback) { context = this.setContext(context, userParams, callback); context.title = tiddler.title; // XXX: not required!? var uriTemplate = "%0/bags/%1/tiddlers/%2"; var host = context.host || this.fullHostName(tiddler.fields["server.host"]); var bag = tiddler.fields["server.bag"]; if(!bag) { return adaptor.noBagErrorMessage; } var uri = uriTemplate.format([host, adaptor.normalizeTitle(bag), adaptor.normalizeTitle(tiddler.title)]); var etag = adaptor.generateETag({ type: "bag", name: bag }, tiddler); var headers = etag ? { "If-Match": etag } : null; var req = httpReq("DELETE", uri, adaptor.deleteTiddlerCallback, context, headers, null, null, null, null, true); return typeof req == "string" ? req : true; }; adaptor.deleteTiddlerCallback = function(status, context, responseText, uri, xhr) { context.status = [204, 1223].contains(xhr.status); context.statusText = xhr.statusText; context.httpStatus = xhr.status; if(context.callback) { context.callback(context, context.userParams); } }; // compare two revisions of a tiddler (requires TiddlyWeb differ plugin) adaptor.prototype.getTiddlerDiff = function(title, context, userParams, callback) { context = this.setContext(context, userParams, callback); context.title = title; var tiddler = store.getTiddler(title); try { var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]); } catch(ex) { return adaptor.locationIDErrorMessage; } var tiddlerRef = [workspace.type + "s", workspace.name, tiddler.title].join("/"); var rev1 = context.rev1 ? [tiddlerRef, context.rev1].join("/") : tiddlerRef; var rev2 = context.rev2 ? [tiddlerRef, context.rev2].join("/") : null; var uriTemplate = "%0/diff?rev1=%1"; if(rev2) { uriTemplate += "&rev2=%2"; } if(context.format) { uriTemplate += "&format=%3"; } var host = context.host || this.fullHostName(tiddler.fields["server.host"]); var uri = uriTemplate.format([host, adaptor.normalizeTitle(rev1), adaptor.normalizeTitle(rev2), context.format]); if(rev2) { var req = httpReq("GET", uri, adaptor.getTiddlerDiffCallback, context, null, null, null, null, null, true); } else { var payload = { title: tiddler.title, text: tiddler.text, modifier: tiddler.modifier, tags: tiddler.tags, fields: $.extend({}, tiddler.fields) }; // XXX: missing attributes!? payload = $.toJSON(payload); req = httpReq("POST", uri, adaptor.getTiddlerDiffCallback, context, null, payload, adaptor.mimeType, null, null, true); } return typeof req == "string" ? req : true; }; adaptor.getTiddlerDiffCallback = function(status, context, responseText, uri, xhr) { context.status = status; context.statusText = xhr.statusText; context.httpStatus = xhr.status; context.uri = uri; if(status) { context.diff = responseText; } if(context.callback) { context.callback(context, context.userParams); } }; // generate tiddler information adaptor.prototype.generateTiddlerInfo = function(tiddler) { var info = {}; var uriTemplate = "%0/%1/%2/tiddlers/%3"; var host = this.host || tiddler.fields["server.host"]; // XXX: this.host obsolete? host = this.fullHostName(host); var workspace = adaptor.resolveWorkspace(tiddler.fields["server.workspace"]); info.uri = uriTemplate.format([host, workspace.type + "s", adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(tiddler.title)]); return info; }; // create Tiddler instance from TiddlyWeb tiddler JSON adaptor.toTiddler = function(json, host) { var created = Date.convertFromYYYYMMDDHHMM(json.created); var modified = Date.convertFromYYYYMMDDHHMM(json.modified); var fields = json.fields; fields["server.type"] = adaptor.serverType; fields["server.host"] = AdaptorBase.minHostName(host); fields["server.bag"] = json.bag; fields["server.title"] = json.title; if(json.recipe) { fields["server.recipe"] = json.recipe; } if(json.type && json.type != "None") { fields["server.content-type"] = json.type; } fields["server.permissions"] = json.permissions.join(", "); fields["server.page.revision"] = json.revision; fields["server.workspace"] = "bags/" + json.bag; var tiddler = new Tiddler(json.title); tiddler.assign(tiddler.title, json.text, json.modifier, modified, json.tags, created, json.fields, json.creator); return tiddler; }; adaptor.resolveWorkspace = function(workspace) { var components = workspace.split("/"); return { type: components[0] == "bags" ? "bag" : "recipe", name: components[1] || components[0] }; }; adaptor.generateETag = function(workspace, tiddler) { var revision = tiddler.fields["server.page.revision"]; var etag = revision == "false" ? null : tiddler.fields["server.etag"]; if(!etag && workspace.type == "bag") { if(typeof revision == "undefined") { revision = "0"; } else if(revision == "false") { return null; } etag = [adaptor.normalizeTitle(workspace.name), adaptor.normalizeTitle(tiddler.title), revision].join("/"); etag = '"' + etag + '"'; } return etag; }; adaptor.normalizeTitle = function(title) { return encodeURIComponent(title); }; })(jQuery); /* * jQuery JSON Plugin * version: 1.3 * source: http://code.google.com/p/jquery-json/ * license: MIT (http://www.opensource.org/licenses/mit-license.php) */ (function($){function toIntegersAtLease(n) {return n 0) { tiddler.fields.changecount -= context.changecount; } plugin.reportSuccess("saved", tiddler); store.setDirty(false); } else { if(context.httpStatus == 412) { plugin.reportFailure("saveConflict", tiddler); } else { plugin.reportFailure("saveError", tiddler, context); } } }; plugin.removeTiddler = function(tiddler) { try { var adaptor = this.getTiddlerServerAdaptor(tiddler); } catch(ex) { return false; } var context = { host: tiddler.fields["server.host"], workspace: tiddler.fields["server.workspace"], tiddler: tiddler }; var req = adaptor.deleteTiddler(tiddler, context, {}, this.removeTiddlerCallback); return req ? tiddler : false; }; plugin.removeTiddlerCallback = function(context, userParams) { var tiddler = context.tiddler; if(context.status) { if(tiddler.fields.deleted === "true") { store.deleteTiddler(tiddler.title); } else { plugin.reportFailure("deleteLocalError", tiddler); } plugin.reportSuccess("deleted", tiddler); store.setDirty(false); } else { plugin.reportFailure("deleteError", tiddler, context); } }; plugin.getTiddlerServerAdaptor = function(tiddler) { // XXX: rename? var type = tiddler.fields["server.type"] || config.defaultCustomFields["server.type"]; return new config.adaptors[type](); }; plugin.reportSuccess = function(msg, tiddler) { displayMessage(plugin.locale[msg].format([tiddler.title])); }; plugin.reportFailure = function(msg, tiddler, context) { var desc = (context && context.httpStatus) ? context.statusText : plugin.locale.connectionError; displayMessage(plugin.locale[msg].format([tiddler.title, desc])); }; config.macros.saveToWeb = { // XXX: hijack existing sync macro? locale: { // TODO: merge with plugin.locale? btnLabel: "save to web", btnTooltip: "synchronize changes", btnAccessKey: null }, handler: function(place, macroName, params, wikifier, paramString, tiddler) { createTiddlyButton(place, this.locale.btnLabel, this.locale.btnTooltip, plugin.sync, null, null, this.locale.btnAccessKey); } }; window.saveChanges = function(onlyIfDirty, tiddlers) { plugin.sync(tiddlers); }; // override removeTiddler to flag tiddler as deleted -- XXX: use hijack to preserve compatibility? TiddlyWiki.prototype.removeTiddler = function(title) { // XXX: should override deleteTiddler instance method? var tiddler = this.fetchTiddler(title); if(tiddler) { tiddler.tags = ["excludeLists", "excludeSearch", "excludeMissing"]; tiddler.text = plugin.locale.removedNotice; tiddler.fields.deleted = "true"; // XXX: rename to removed/tiddlerRemoved? tiddler.fields.changecount = "1"; this.notify(title, true); this.setDirty(true); } }; // hijack ImportTiddlers wizard to handle cross-domain restrictions var _onOpen = config.macros.importTiddlers.onOpen; config.macros.importTiddlers.onOpen = function(ev) { var btn = $(resolveTarget(ev)); var url = btn.closest(".wizard").find("input[name=txtPath]").val(); if(window.location.protocol != "file:" && url.indexOf("://") != -1) { var host = url.split("/")[2]; var macro = config.macros.importTiddlers; if(host != window.location.host) { btn.text(macro.cancelLabel).attr("title", macro.cancelPrompt); btn[0].onclick = macro.onCancel; $('<span/>').text(plugin.locale.hostError).insertAfter(btn); return false; } } return _onOpen.apply(this, arguments); }; })(jQuery); //}}} //-- //-- Backstage //-- // Backstage tasks config.tasks.save.action = saveChanges; var backstage = { area: null, toolbar: null, button: null, showButton: null, hideButton: null, cloak: null, panel: null, panelBody: null, panelFooter: null, currTabName: null, currTabElem: null, content: null, init: function() { var cmb = config.messages.backstage; this.area = document.getElementById("backstageArea"); this.toolbar = jQuery("#backstageToolbar").empty()[0]; this.button = jQuery("#backstageButton").empty()[0]; this.button.style.display = "block"; var t = cmb.open.text + " " + glyph("bentArrowLeft"); this.showButton = createTiddlyButton(this.button,t,cmb.open.tooltip, function(e) {backstage.show(); return false;},null,"backstageShow"); t = glyph("bentArrowRight") + " " + cmb.close.text; this.hideButton = createTiddlyButton(this.button,t,cmb.close.tooltip, function(e) {backstage.hide(); return false;},null,"backstageHide"); this.cloak = document.getElementById("backstageCloak"); this.panel = document.getElementById("backstagePanel"); this.panelFooter = createTiddlyElement(this.panel,"div",null,"backstagePanelFooter"); this.panelBody = createTiddlyElement(this.panel,"div",null,"backstagePanelBody"); this.cloak.onmousedown = function(e) {backstage.switchTab(null);}; createTiddlyText(this.toolbar,cmb.prompt); for(t=0; t<config t="" var="" taskname="config.backstageTasks[t];" console="" task="config.tasks[taskName];" handler="task.action" this="" :="" text="task.text" glyph="" btn="createTiddlyButton(this.toolbar,text,task.tooltip,handler,"backstageTab");" jquery="" document="" if="" else="" isvisible:="" function="" return="" false="" show:="" config="" backstage="" findwindowwidth="" p="[{style:" start:="" end:="" template:="" anim="" morpher="" true="" saveoption="" hide:="" c="function(element,properties)" onclickcommand:="" onclicktab:="" switch="" to="" a="" given="" tab="" or="" none="" null="" is="" passed="" switchtab:="" tabelem="null;" e="this.toolbar.firstChild;" while="" tabname="" wikify="" ispanelvisible:="" preparepanel:="" finddocheight="" showpanel:="" scroller="" hidepanel:="" atend:="" backstagetask="config.tasks[params[0]];" createtiddlybutton="" main="" params="null;" command="" line="" parameters="" store="null;" tiddlywiki="" storage="" story="null;" formatter="null;" default="" formatters="" for="" the="" wikifier="" animator="=" new="" animation="" engine="" readonly="false;" whether="" we="" in="" mode="" highlighthack="null;" embarrassing="" hack="" department="" hadconfirmexit="false;" don="" warn="" more="" than="" once="" safemode="false;" disable="" all="" plugins="" and="" cookies="" showbackstage="" include="" area="" installedplugins="[];" information="" filled="" when="" are="" executed="" startingup="false;" process="" of="" starting="" up="" plugininfo="" used="" pass="" loadplugins="" space="" total_tiddlers="-1;" ajaxreq="" datatype:="" url:="" success:="" host="window.location.protocol" window="" workspace="recipes/" status="" defaults="config.defaultCustomFields;" filter="?select=tag:excludeLists&type:!text/css&select=type:!text/html&select=type:!image/png&select=type:!image/jpg&select=type:!image/gif&select=type:!image/jpeg" time="0," start="0," total="50;" lazy_load_content="function(title)" data:="" i="0;" tids="" tid="config.adaptors.tiddlyweb.toTiddler(tids[i],"> -1) { var pc = 100 - Math.floor(((total_tiddlers - store.getTiddlers().length) / total_tiddlers) * 100); displayMessage(pc + "% of document loaded."); } start += total; time += 100; lazy_load_content(title); } }, }); }, time); } var success = function(json) { store = new TiddlyWiki({config:config}); invokeParamifier(params,"oninit"); story = new Story("tiddlerDisplay","tiddler"); jQuery("#contentWrapper").removeClass("loading"); for(var i = 0; i 0) { plugin.log.push(config.messages.pluginVersionError); return false; } } return true; } function isPluginEnabled(plugin) { if(plugin.tiddler.isTagged("systemConfigDisable")) { plugin.log.push(config.messages.pluginDisabled); return false; } return true; } </config>

    Syndicated 2012-03-13 13:31:46 (Updated 2012-03-13 13:32:01) from cdent

    Latest blog entries     Older blog entries

    New Advogato Features

    New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

    Keep up with the latest Advogato features by reading the Advogato status blog.

    If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!