PageRenderTime 36ms CodeModel.GetById 7ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

/extras/t2tformatterplugin.tiddly

http://txt2tags.googlecode.com/
Unknown | 952 lines | 888 code | 64 blank | 0 comment | 0 complexity | b9a2656348a8e54e7ea5cd5796347f74 MD5 | raw file
  1/***
  2|''Name:''|T2tFormatterPlugin|
  3|''Description:''|Allows Tiddlers to use [[txt2tags|http://txt2tags.org/markup.html]] formatting|
  4|''Author:''|David Young (david (dot) a (dot) young (at) gmail (dot) com)|
  5|''Credit:''|Copied and modified from Martin Budden's http://www.martinswiki.com/#ExampleFormatterPlugin |
  6|''CodeRepository:''|NA |
  7|''Version:''|0.4|
  8|''Status:''|Rough Draft|
  9|''Date:''|Jul 5, 2011|
 10|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
 11|''License:''|NA |
 12|''~CoreVersion:''|2.6.1|
 13
 14! Installation Instructions
 15
 16Apply the following tags to this tiddler:
 17
 18* systemConfig
 19* excludeLists
 20* excludeSearch
 21
 22You can make a tiddler with the tag ''t2t'' and the Txt2Tags markup will be used instead of TiddlyWiki markup. You can eliminate the need to manually tag by modifying your ''Create New Tiddler'' macro in your [[MainMenu]] to set the //wikiformat// field to ''t2t'':
 23
 24{{{
 25<<newTiddler
 26label: "New t2t"
 27title: "New t2t tiddler"
 28fields: "wikiformat:t2t"
 29prompt: "Create a new tiddler using the t2t formatter">>
 30}}}
 31
 32You should also get into [[AdvancedOptions]] or //backstage -> Tweaks -> chkInsertTabs// because that lets you hit the tab button in the tiddly text field.  Tab will still move your cursor around the page, from title input to tiddly text input, etc. It only effects the text field.  Vital for t2t blockquote syntax (prepending with tabs).
 33
 34!Features/ Progress
 35
 36| ''Markup'' | ''Feature'' | ''Status'' | ''Version'' | ''Comment'' |
 37| several | \n vs. \r in input | ''WAITING'' | NA |Applied to tagged and raw, but I am uncertain if this is OK.<br>Emailed twdev mailing list. |
 38| ''FONT/INLINE'' |||||
 39|{{{**}}}''bold''{{{**}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 40|{{{//}}}//italic//{{{//}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 41|{{{__}}}__under__{{{__}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 42|{{{--}}}--strike--{{{--}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.|
 43|{{{^^}}}^^super^^{{{^^}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.<br>Not Official Markup.|
 44|{{{,,}}}~~sub~~{{{,,}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.<br>Not Official Markup.|
 45|{{{``monospace``}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.|
 46|{{{''}}}tagged/html{{{''}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.|
 47|{{{""}}}raw{{{""}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.<br>Overrides WikiWords and Markup.|
 48| ''SINGLE-LINE'' |||||
 49|{{{``` monospace}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 50|{{{'''}}} tagged/html | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 51|{{{"""}}} raw | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 52|{{{%}}}comments | ALL | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 53| ''BLOCKS'' |||||
 54|{{{```}}}<br>{{{monospace}}}<br>{{{```}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 55|{{{'''}}}<br>tagged/html<br>{{{'''}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 56|{{{"""}}}<br>raw<br>{{{"""}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 57|{{{%%%}}}<br>comments<br>{{{%%%}}} | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform |
 58|\t<html>&nbsp;&nbsp;&nbsp;&nbsp;</html>block<br>\t<html>&nbsp;&nbsp;&nbsp;&nbsp;</html>quotes | All | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.<br>Tiddlywiki interprets all markup inside the block; unlike txt2tags (only some markup). |
 59| ''HEADERS'' |||||
 60|{{{=}}}un-numbered{{{=}}} | ALL | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 61|{{{+}}}numbered{{{+}}} | HEADING | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 62|{{{+}}}numbered{{{+}}} | NUMBERING | ''OK'' | 0.1 |Hasn't been heavily tested on any platform.<br>Unknown if array length modification or array[6] reassignment is faster on a per-iteration basis. |
 63| ''MISC'' |||||
 64|horizontal rule<br>{{{--------------------}}} | RULE | ''OK'' | 0.1 |Hasn't been heavily tested on any platform. |
 65|{{{====================}}}<br>{{{____________________}}}| THICKNESS | ''??'' | 0.1 |The alternative rules are interpreted and classes //heavy// or //light// are assigned; but my theme doesn't use them so I can't tell.<br>Maybe tiddlywiki doesn't use those css classes at all?<br>If so, delete this functionality. |
 66|Paragraphs | ALL | ''CAN'T FIX'' | 0.1 |Multiple newlines are concatenated into {{{<p><\p>}}}.<br>Visually they appear correctly (line spacing, etc), but it isn't a real paragraph.<br>If you try to make {{{<p>}}} elements wrap the text, then they are nested improperly if you look at the html.<br>This nesting lead to a stack busting on tiddlers if you have around 200 paragraphs or more.<br>This resulted in content truncation, so {{{<p><\p>}}} it shall be.<br>Historical bug in tiddlywiki's core, so I can't do much about it.<br>This is certainly a kludge, maybe {{{<br><br>}}} would be better, but that seems equally kludgy and all block-type syntax must be careful. |
 67| ''LISTS'' |||||
 68|{{{- }}}unordered | ALL | ''OK'' | 0.1 |t2t allows complex lists (paragraphs inside list items).<br>Can't figure out a good regex to match "X blank lines" that works with paragraph.<br>Interim solution: terminate list with empty item. |
 69|{{{+ }}}ordered | ALL | ''OK'' | 0.1 |t2t allows complex lists (paragraphs inside list items).<br>Can't figure out a good regex to match "X blank lines" that works with paragraph.<br>Interim solution: terminate list with empty item.<br>INTERFERES WITH NUMBERED HEADINGS. |
 70|{{{: }}}word<br><html>&nbsp;&nbsp;&nbsp;&nbsp;</html>definitions | ALL | ''TIDDLY'' | NA |Difficult to pull off since "definition" part of t2t uses whitespaces.<br>Interim solution: use tiddlywiki ; word \n : definition format. |
 71| ''COMPLEX'' |||||
 72|~WikiWords | ALL | ''TIDDLY'' | 0.1 |Self-updating link to core formatter.<br>Not Official Markup. |
 73|{{{<<macros>>}}} | ALL | ''TIDDLY'' | 0.1 |Self-updating link to core formatter.<br>By changing the header syntax, the {{{<<tiddler##section>>}}} section transclusion macro won't work.<br>Not Official Markup. |
 74|http url recognition | ALL | ''TIDDLY'' | 0.1 |Self-updating link to core formatter.<br>Not Official Markup. |
 75|email recognition | ALL | ''NA'' | NA |Is this at all worth it?  t2t will mask or convert to mailto...<br>don't take this lightly- it wrecked the works last time. |
 76|{{{[}}}links{{{]}}} | ALL | ''OK'' | 0.1 |Links to internal tiddlers (as long as their title has no spaces), links to external websites |
 77|{{{[}}}named links{{{]}}} | ALL | ''OK'' | 0.1 |Links to internal tiddlers (as long as their title has no spaces), links to external websites |
 78|'image-related' | ALL | ''OK'' | 0.1 |an image or image link supports whitespace-alignment.<br>If the {{{[}}} starts at the newline, the image will float to the left (equivalent to the {{{<}}} markup in tiddly images).<br>If the {{{]}}} ends the line, the image will float to the right (equivalent to the {{{>}}} markup in tiddly images).<br>If the image is both the start and end of line, it is neither left nor right.<br>No centering image support yet. |
 79|{{{[}}}images{{{]}}} | ALL | ''OK'' | 0.1 |Supports .png .gif .jpg .jpeg, just grep for IMAGE-EXTENSION-REGEX in this tiddler to expand the list.<br>Works for local and external image files |
 80|{{{[[image] links]}}} | ALL | ''OK'' | 0.1 |A twist here is that the link can have spaces in the name, but I don't recommend trying that. |
 81|{{{|}}}tables{{{|}}} | ALL | ''TIDDLY'' | 0.1 |Tiddlywiki tables are supported. Self-updating link to core formatter. |
 82
 83***/
 84
 85//{{{
 86//REGEXES found in txt2tags.py:1920 (getRegexes)
 87// Ensure that the plugin is only installed once.
 88
 89if(!version.extensions.T2tFormatterPlugin) {
 90version.extensions.T2tFormatterPlugin = {installed:true};
 91
 92//Should test this backwards until I find the revision that is actually useless
 93if(version.major < 2 || (version.major == 2 && version.minor < 6))
 94	{alertAndThrow('T2tFormatterPlugin requires TiddlyWiki 2.6 or later.');}
 95
 96t2tFormatter = {}; // 'namespace' for local functions
 97
 98t2tDebug = function(out,str)
 99{
100	createTiddlyText(out,str.replace(/\n/mg,'\\n').replace(/\r/mg,'RR'));
101	createTiddlyElement(out,'br');
102};
103
104/*
105wikify = function(source,output,highlightRegExp,tiddler)
106{
107	if(source && source !== '') {
108		var w = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
109		w.output = tiddler ? createTiddlyElement(output,'p') : output;
110		w.subWikifyUnterm(w.output);
111	}
112};
113*/
114
115// COPY from EnclosedTextHelper Tiddlywiki v2.6.1 line 2923
116// If the lookaheadRegexp fails, use the string in "restore:"
117// define the element "restore:" as the static string equal to your
118// "match:"'s result.
119//
120// If your markup rules are more complex/less dynamic (like ==headers==);
121// then you must copy this and make up your own combo of parenthesis.
122config.formatterHelpers.nonDestructiveEnclosedTextHelper = function(w)
123{
124	this.lookaheadRegExp.lastIndex = w.matchStart;
125	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
126	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
127		//Everything that uses this function is a one-liner syntax
128		/*
129		var text = lookaheadMatch[1];
130		if(config.browser.isIE)
131			text = text.replace(/\n/g,"\r");
132		createTiddlyElement(w.output,this.element,null,null,text);
133		*/
134		//createTiddlyElement(w.output,this.element,null,null,lookaheadMatch[1]);
135		w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
136		w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
137	} else {
138		w.output.appendChild(document.createTextNode(w.matchText));
139	}
140};
141
142/*
143// Like nonDestructiveEnclosedTextHelper, only you can define what is
144// restored with a regular expression instead of a static string.
145// This is helpful for when the "match" is more dynamic. Just define
146// element "restoreRegExp:" and the first parenthesis in it will be used
147// to restore the consumed "match" text.
148// NOTE: this comes at the cost of ANOTHER grepping of your input!
149config.formatterHelpers.nonDestructiveEnclosedTextHelperRegEx = function(w)
150{
151	this.lookaheadRegExp.lastIndex = w.matchStart;
152	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
153	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
154		var text = lookaheadMatch[1];
155		if(config.browser.isIE)
156			text = text.replace(/\n/g,"\r");
157		createTiddlyElement(w.output,this.element,null,null,text);
158		w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
159	} else {
160		this.restoreRegExp.lastIndex = w.matchStart;
161		var restoreMatch = this.restoreRegExp.exec(w.source);
162		if (restoreMatch && restoreMatch.index == w.matchStart) {
163			w.output.appendChild(document.createTextNode(restoreMatch[1]));
164		} else {
165			//shouldn't be possible!
166			//Only if you don't define restoreRegExp: properly
167			w.output.appendChild(document.createTextNode("### SYNTAX ERROR ###"));
168		}
169	}
170};
171*/
172
173/*
174config.formatterHelpers.setAttributesFromParams = function(e,p)
175{
176	var re = /\s*(.*?)=(?:(?:"(.*?)")|(?:'(.*?)')|((?:\w|%|#)*))/mg;
177	var match = re.exec(p);
178	while(match) {
179		var s = match[1].unDash();
180		if(s=='bgcolor') {
181			s = 'backgroundColor';
182		}
183		try {
184			if(match[2]) {
185				e.setAttribute(s,match[2]);
186			} else if(match[3]) {
187				e.setAttribute(s,match[3]);
188			} else {
189				e.setAttribute(s,match[4]);
190			}
191		}
192		catch(ex) {}
193		match = re.exec(p);
194	}
195};
196*/
197
198config.t2tFormatters = [
199
200//SPEED: COMBINE ALL BEAUTIFIERS LIKE TIDDLY DOES ALREADY
201// bold uses syntax **bold** no whitespace in the bookends.
202{
203	name: 't2tBold',
204	match: '\\*\\*',
205	element: 'strong',
206	lookaheadRegExp: /\*\*([^\s](|.*?[^\s])\**)\*\*/mg,
207	termRegExp: /(\*\*)/mg,
208	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
209},
210
211// italic uses //italic//
212{
213	name: 't2tItalic',
214	match: '//',
215	element: 'em',
216	lookaheadRegExp: /\/\/([^\s](|.*?[^\s])[\/]*)(\/\/)/mg,
217	termRegExp: /(\/\/)/mg,
218	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
219},
220
221// Horizontal rules can be made up of 20 or more - characters on a line with
222// whitespace on the ends. Alternatively 20 or more _ characters is accepted.
223// 20 or more = characters also work, but that makes a "thicker" horizontal rule
224// see t2tHeavyRule.
225{
226	name: 't2tRule',
227	match: '^[ \\t]*[-_]{20,}[ \\t]*$',
228	handler: function(w)
229	{
230		createTiddlyElement(w.output,'hr',null,'light');
231	}
232},
233
234// Default tiddler theme doesn't differentiate between heavy and light.
235// TODO: Try some other themes otherwise roll this into t2tRule.
236{
237	name: 't2tHeavyRule',
238	match: '^[ \\t]*={20,}[ \\t]*$',
239	handler: function(w)
240	{
241		createTiddlyElement(w.output,'hr',null,'heavy');
242	}
243},
244
245// underline uses __underline__
246{
247	name: 't2tUnderline',
248	match: '__',
249	element: 'ins',
250	lookaheadRegExp: /__([^\s](|.*?[^\s])_*)__/mg,
251	termRegExp: /(__)/mg,
252	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
253},
254
255// strikethrough uses --strike--
256{
257	name: 't2tStrike',
258	match: '--',
259	element: 'del',
260	lookaheadRegExp: /--([^\s](|.*?[^\s])-*)--/mg,
261	termRegExp: /(--)/mg,
262	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
263},
264
265/*
266// superscript uses ^^super^^
267// this is unofficial
268{
269	name: 't2tSuperscript',
270	match: '\\^\\^',
271	element: 'sup',
272	lookaheadRegExp: /\^\^([^\s](|.*?[^\s])\^*)\^\^/mg,
273	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
274},
275
276// subscript uses ,,sub,,
277// this is unofficial
278{
279	name: 't2tSubscript',
280	match: ',,',
281	element: 'sub',
282	lookaheadRegExp: /,,([^\s](|.*?[^\s]),*),,/mg,
283	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
284},
285*/
286
287// Monospace uses different variants of backticks
288// blocks are bordered with lines containing only 3 backticks
289// ```
290{
291	name: 't2tMonospaceBlock',
292	match: '^```[ \\t]*$',
293	lookaheadRegExp: /^```[ \t]*(?:\n?((?:.|\n)*?\n)```[ \t]*$)|((?:.|\n)*$)/gm,
294	handler: function(w) {
295		this.lookaheadRegExp.lastIndex = w.matchStart;
296		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
297		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
298			if (lookaheadMatch[1]) {
299				var text = lookaheadMatch[1];
300			} else {
301				var text = lookaheadMatch[2].substr(w.matchLength+1);
302			}
303			if(config.browser.isIE)
304				text = text.replace(/\n/g,"\r");
305			createTiddlyElement(w.output,"pre",null,null,text);
306			w.nextMatch = this.lookaheadRegExp.lastIndex;
307		} else  w.output.appendChild(document.createTextNode(w.matchText));
308	}
309},
310
311// lines prefixed with 3 backticks are preformatted blocks as well
312// one block per line! putting backtic-prefixed lines consecutively will
313// result in 2 preformatted blocks!
314//SPEED: this can be like tiddly's termregexp syntax like a "Heading"
315{
316	name: 't2tMonospaceLine',
317	match: '^``` ',
318	lookaheadRegExp: /^``` ((?:.)*?)$/mg,
319	element: 'pre',
320	handler: config.formatterHelpers.enclosedTextHelper
321},
322
323// inline monospaced text ``like this``.
324// terminates at the first newline without matching backtics.
325// this version uses code instead of pre.
326{
327	name: 't2tMonospace',
328	match: '``',
329	element: 'code',
330	lookaheadRegExp: /``([^\s](|.*?[^\s])`*)``/mg,
331	termRegExp: /(``)/mg,
332	handler: config.formatterHelpers.nonDestructiveEnclosedTextHelper
333},
334
335//t2tCommentblock
336{
337	name: 't2tCommentBlock',
338	match: '^%%%[ \\t]*\\n',
339	//emptyblock but no unclosed trailer
340	//lookaheadRegExp: /^%%%[ \t]*((?:.|\n)*?)\n%%%[ \t]*(\n|$)/mg,
341	//                           match next %%% line   OR match to EOF
342	lookaheadRegExp: /^%%%[ \t]*(?:(?:[.|\n]*?)\n%%%[ \t]*$)|(?:[.\n]*$)/gm,
343	handler: function(w)
344	{
345		this.lookaheadRegExp.lastIndex = w.matchStart;
346		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
347		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
348			w.nextMatch = this.lookaheadRegExp.lastIndex;
349		} else  w.output.appendChild(document.createTextNode(w.matchText));
350	}
351},
352
353//SPEED: this can be like tiddly's termregexp syntax like a "Heading"
354{
355	name: 't2tCommentLine',
356	match: '^%' ,
357	lookaheadRegExp: /^%.*?$/mg,
358	handler: function(w)
359	{
360		this.lookaheadRegExp.lastIndex = w.matchStart;
361		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
362		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
363			w.nextMatch = this.lookaheadRegExp.lastIndex;
364		} else  w.output.appendChild(document.createTextNode(w.matchText));
365	}
366},
367
368// nonstandard br insertion
369// I like tex's \\
370{
371	name: 't2tLineBreak',
372	match: '\\\\\\\\',
373	handler: function(w)
374	{
375		createTiddlyElement(w.output,'br');
376	}
377},
378
379//TODO: tagged text doesn't get the \n \r IE replacement... test in IE
380// t2t tagged text is "passthrough" so what you type is passed on to
381// the html interpreter. t2t formatting isn't converted into html.
382// Raw html is interpreted by your browser.
383// Tagged uses various forms of single-quotes.
384// multi-line blocks are bordered by lines containing only '''
385{
386	name: 't2tTaggedBlock',
387	match: '^\'\'\'[ \\t]*$',
388	lookaheadRegExp: /^'''[ \t]*(?:((?:.|\n)*?\n)'''[ \t]*$)|((?:.|\n)*$)/gm,
389	handler: function(w)
390	{
391		this.lookaheadRegExp.lastIndex = w.matchStart;
392		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
393		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
394			if (lookaheadMatch[1]) {
395				var text = lookaheadMatch[1];
396			} else {
397				var text = lookaheadMatch[2].substr(w.matchLength+1);
398			}
399			if(config.browser.isIE)
400				text = text.replace(/\n/g,"\r");
401			createTiddlyElement(w.output,"span").innerHTML = text;
402			w.nextMatch = this.lookaheadRegExp.lastIndex;
403		} else  w.output.appendChild(document.createTextNode(w.matchText));
404	}
405},
406
407// Single lines prepended with ''' will be considered "tagged"
408// Unlike monospace, tagged isn't really a "block" so having multiple
409// pre-pended lines won't look any different than one multi-line block.
410//SPEED: this can be like tiddly's termregexp syntax like a "Heading"
411{
412	name: 't2tTaggedLine',
413	match: '^\'\'\' ',
414	lookaheadRegExp: /^''' ((?:.)*?)$/mg,
415	handler: function(w)
416	{
417		this.lookaheadRegExp.lastIndex = w.matchStart;
418		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
419		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
420			createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1];
421			w.nextMatch = this.lookaheadRegExp.lastIndex;
422		} else  w.output.appendChild(document.createTextNode(w.matchText));
423	}
424},
425
426// inline tagged text is wrapped ''in 2 single quotes''.  This type ends at
427// the newline if there is no matching ''.
428{
429	name: 't2tTagged',
430	match: '\'\'',
431	lookaheadRegExp: /''([^\s](|.*?[^\s])'*)''/mg,
432	handler: function(w)
433	{
434		this.lookaheadRegExp.lastIndex = w.matchStart;
435		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
436		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
437			createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1];
438			w.nextMatch = this.lookaheadRegExp.lastIndex;
439		} else  w.output.appendChild(document.createTextNode(w.matchText));
440	}
441},
442
443//TODO: RAW text doesn't get the \n \r IE replacement... test in IE
444// t2t Raw text ignores t2t formatting (any wiki formatting); but characters
445// are still 'escaped' out to be displayed by the brower.
446// e.g. ""**bold**"" isn't made bold; you see the astrices; while lines using
447// html tags will convert angle brackets to < >
448// This is synonymous with nowiki
449
450// Blocks of raw text are bordered with blank lines of 3 double quotes.
451{
452	name: 't2tRawBlock',
453	match: '^\\"\\"\\"[ \\t]*$',
454	lookaheadRegExp: /^"""[ \t]*(?:((?:.|\n)*?\n)"""[ \t]*$)|((?:.|\n)*$)/gm,
455	handler: function(w)
456	{
457		this.lookaheadRegExp.lastIndex = w.matchStart;
458		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
459		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
460			if (lookaheadMatch[1]) {
461				var text = lookaheadMatch[1];
462			} else {
463				var text = lookaheadMatch[2].substr(w.matchLength+1);
464			}
465			//rawblock may not work with this properly?
466			if(config.browser.isIE)
467				text = text.replace(/\n/g,"\r");
468			createTiddlyElement(w.output,"span",null,null,text);
469			w.nextMatch = this.lookaheadRegExp.lastIndex;
470		} else  w.output.appendChild(document.createTextNode(w.matchText));
471	}
472},
473
474// Any line prepended with 3 double quotes is interpreted as raw.
475// Unlike monospace, raw isn't really a "block" so consecutive pre-pended lines
476// will have no difference with a multi-line block.
477//SPEED: this can be like tiddly's termregexp syntax like a "Heading"
478{
479	name: 't2tRawLine',
480	match: '^\\"\\"\\" ',
481	lookaheadRegExp: /^""" ((?:.)*?)$/mg,
482	handler: function(w)
483	{
484		this.lookaheadRegExp.lastIndex = w.matchStart;
485		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
486		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
487			createTiddlyElement(w.output,'span',null,null,lookaheadMatch[1]);
488			w.nextMatch = this.lookaheadRegExp.lastIndex;
489		} else  w.output.appendChild(document.createTextNode(w.matchText));
490	}
491},
492
493// The in-line format uses 2 double quotes ""raw"".
494// The end of the line terminates raw if there is no matching "".
495{
496	name: 't2tRaw',
497	match: '\\"\\"',
498	lookaheadRegExp: /""([^\s](|.*?[^\s])"*)""/mg,
499	handler: function(w)
500	{
501		this.lookaheadRegExp.lastIndex = w.matchStart;
502		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
503		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
504			createTiddlyElement(w.output,'span',null,null,lookaheadMatch[1]);
505			w.nextMatch = this.lookaheadRegExp.lastIndex;
506		} else  w.output.appendChild(document.createTextNode(w.matchText));
507	}
508},
509
510// Section headings are bookended by matching sets of = signs.
511// It must all be on one line
512//SPEED: simplify match
513{
514	name: 't2tHeading',
515	//no whitespace at the start
516	//match: '^ *={1,6}[^=\n]',
517	//lookaheadRegExp: /^ *(={1,6})([^=\n][^\n]*[^=\n])\1[ \t]*$/mg,
518	match: '^={1,6}[^ =\n]',
519	lookaheadRegExp: /^(={1,6})([^ =\n][^\n]*[^=\n])\1[ \t]*$/mg,
520	handler: function(w)
521	{
522		this.lookaheadRegExp.lastIndex = w.matchStart;
523		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
524		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
525			//headings in t2t don't allow markup inside, so we DO NOT use the subwikifyterm here.
526			createTiddlyElement(w.output,'h'+lookaheadMatch[1].length,null,null,lookaheadMatch[2]);
527			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
528		} else  w.output.appendChild(document.createTextNode(w.matchText));
529	}
530},
531
532/*
533//This breaks everything.  T2T converts emails into mailto:s or it masks them:
534// dave@gmail.com --> <dave (AT) gmail dOT com>
535{
536	name: 't2tEmailHiding',
537	match: '[\\w]+(\\.[\\w\\-\\+_]+)*\\@[\\w\\-\\+_]+\\.[\\w\\-\\+_]+(\\.[\\w\\-\\+_]+)*',
538	lookaheadRegExp: /([\w]+(?:\.[\w\-\+_]+)*)\@([\w\-\+_]+\.[\w\-\+_]+(?:\.[\w\-\+_]+)*)/mg,
539	handler: function(w)
540	{
541		this.lookaheadRegExp.lastIndex = w.matchStart;
542		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
543		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
544			var text = '<' + lookaheadMatch[1] + " (AT) " + lookaheadMatch[2] + '>';
545			text = text.replace(/\./g," DOT ");
546			createTiddlyElement(w.output,"span",null,null,text);
547			w.nextMatch = this.lookaheadRegExp.lastIndex;
548		}
549	}
550},
551*/
552
553// push-pop version keeps the array sized to whatever it should be.  This is
554// probably faster than the array reassignment (below this function) especially
555// in the simplest and more likely use case: only using top-level headings.
556// In practice, though, 10k numbered headings takes forever in BOTH cases.
557// HTML doesn't have an inherent number scheme for header tags. Just treat
558// them as unnumbered for now.
559// SPEED: simplify match. see what termregexp can do.
560{
561	name: 't2tNumberedHeading',
562	//no whitespace at the start.
563	//match: '^ *\\+{1,6}[^\\+\\n]',
564	//lookaheadRegExp: /^ *(\+{1,6})([^\+\n][^\n]*[^\+\n])\1[ \t]*$/mg,
565	match: '^\\+{1,6}[^ \\+\\n]',
566	lookaheadRegExp: /^(\+{1,6})([^ \+\n][^\n]*[^\+\n])\1[ \t]*$/mg,
567	handler: function(w)
568	{
569		if (! w.numheading) {
570			w.numheading = [0,0];
571		}
572		this.lookaheadRegExp.lastIndex = w.matchStart;
573		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
574		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
575			var text = lookaheadMatch[2];
576			// since length=1 == arrayindex 0
577			var headingindex = lookaheadMatch[1].length - 1;
578			// since length1 means we want 2 items in the array
579			var targetlength = headingindex + 2;
580			//add or remove values until numheading.length = lookaheadMatch[1].length
581			//push 0's first to add
582			for (var i = w.numheading.length; i < targetlength; i++) 
583				w.numheading.push(0);
584			//removing is eashy, you can just change length and it truncates array (garbage later)
585			w.numheading.length = targetlength;
586			//increment this heading
587			w.numheading[headingindex]++;
588			//reset the next level down to 0
589			w.numheading[headingindex + 1] = 0;
590			text = " " + text;
591			for (headingindex; headingindex >= 0; headingindex--) {
592				text = w.numheading[headingindex] + "." + text;
593			}
594			createTiddlyElement(w.output,'h'+lookaheadMatch[1].length,null,null,text);
595			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
596		} else  w.output.appendChild(document.createTextNode(w.matchText));
597	}
598},
599
600// t2t concatenates newlines to make paragraphs.
601// WARNING: tiddly doesn't support this very well; the appearance is
602// OK but the dynamic HTML has oddly-nested paragraphs.
603{
604	name: 't2tParagraph',
605	match: '\\n{2,}',
606	handler: function(w)
607	{
608		//do you like stack overflows in your html engine?
609		//try making 200 paragraphs with this.
610		//createTiddlyElement(w.output,'p');
611
612		//Looks ok-ish, but now you have manual BR's mixed in
613		//with the implied whitespace by an <h1> or <quote>.
614		//createTiddlyElement(w.output,'br');
615		//createTiddlyElement(w.output,'br');
616
617		//ohh this is so wrong to do, but it works pretty well.
618		//no stack explosions, and it looks visually correct.
619		createTiddlyElement(w.output,"span").innerHTML = "<p></p>";
620	}
621},
622
623{
624	name: 't2tLinkImg',
625	match:  '(?:^\\[)|(?:\\[)',
626	// ([^\n\r]*?) matches 2 separate entities: [foo] and [soft]
627	// ([^\n\r]*) matches entity: [(foo] and [soft)]
628	// use *? or include [] us unallowed chaaracters
629	lookaheadRegExp: /(?:(^\[)|(?:\[))(?:(\[([^\[\]\n\r\f]+)\] ?([^\n\r\[\]]*))|([^\s\[\]]+)|(([^\[\]\n\r\f]+) ([^\[\]\s]+)))(?:(\]$)|(?:\]))/mg,
630	handler: function(w)
631	{
632		this.lookaheadRegExp.lastIndex = w.matchStart;
633		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
634		if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
635		{
636			//first and last group match for alignment to be used for images.
637			if (lookaheadMatch[1] && (! lookaheadMatch[9]))
638			{
639				var imagealign = "left";
640
641			}
642			else if ( (! lookaheadMatch[1]) && lookaheadMatch[9])
643			{
644				var imagealign = "right";
645			}
646			//alignment discovered, now see what type of bracket link.
647
648			// [[image] link]
649			//2 = imglink; 3 img 4 link
650			if (lookaheadMatch[2])
651			{
652				var e = w.output;
653				// 4 may not exist, it could just be an image formatted [[image]]
654				if (lookaheadMatch[4]) {
655					var link = lookaheadMatch[4];
656					e = config.formatterHelpers.isExternalLink(link) ?
657						createExternalLink(w.output,link) :
658						createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
659					addClass(e,"imageLink");
660				}
661				var img = createTiddlyElement(e,"img");
662				if (imagealign) img.align = imagealign;
663				img.src = lookaheadMatch[3];
664				img.title = lookaheadMatch[4];
665				img.setAttribute("alt",lookaheadMatch[4]);
666				w.nextMatch = this.lookaheadRegExp.lastIndex;
667				/*
668				if (align)
669				{
670					alert( align+"-ed image\nfile: '"+lookaheadMatch[3]+"'\nurl: '"+lookaheadMatch[4]+"'");
671				} else {
672					alert( "unaligned image\nfile: '"+lookaheadMatch[3]+"'\nurl: '"+lookaheadMatch[4]+"'");
673				}
674				*/
675			}
676
677			// [link] or [image] 
678			//5 = url or img
679			else if (lookaheadMatch[5])
680			{
681				// IMAGE-EXTENSION-REGEX
682				if (/\.((gif)|(je?pg)|(png)|(bmp)|(tif))$/i.exec(lookaheadMatch[5]))
683				{
684					//alert("image extension found");
685					var e = w.output;
686					var img = createTiddlyElement(e,"img");
687					if (imagealign) img.align = imagealign;
688					img.src = lookaheadMatch[5];
689					img.title = lookaheadMatch[5];
690					img.setAttribute("alt",lookaheadMatch[5]);
691					w.nextMatch = this.lookaheadRegExp.lastIndex;
692					/*
693					if (align)
694					{
695						alert( align+"-ed image\nfile: '"+lookaheadMatch[5]+"'");
696					} else {
697						alert( "unaligned image\nfile: '"+lookaheadMatch[5]+"'");
698					}
699					*/
700				}
701				else
702				{
703					//alert("no image extension found");
704					//obviously this isn't an image by the extension, so it is just a link.
705					var link = lookaheadMatch[5];
706					var e = (config.formatterHelpers.isExternalLink(link)) ?
707						createExternalLink(w.output,link) :
708						createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
709					createTiddlyText(e,link);
710					w.nextMatch = this.lookaheadRegExp.lastIndex;
711					//alert("Simple link to url: '"+lookaheadMatch[5]+"'");
712				}
713			}
714			// [some name text linkWithNoSpaces] the existence of a space is the key!
715			//6 named link 7 = name 8 = link
716			else if (lookaheadMatch[6])
717			{
718				var text = lookaheadMatch[7];
719				var link = lookaheadMatch[8];
720				var e = (config.formatterHelpers.isExternalLink(link)) ?
721					createExternalLink(w.output,link) :
722					createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
723				createTiddlyText(e,text);
724				w.nextMatch = this.lookaheadRegExp.lastIndex;
725				//alert( "name: '"+lookaheadMatch[8]+"'\nurl: '"+lookaheadMatch[9]+"'");
726			} else w.output.appendChild(document.createTextNode(w.matchText));
727		} else w.output.appendChild(document.createTextNode(w.matchText));
728	}
729},
730
731// COPY from tiddlywiki code
732{
733	name: "t2tList",
734	match: "^(?:[ ]*[\\+-;:] )",
735	//lookaheadRegExp: /^(?:[ ]*(?:(-)|(\+)|(:)|( )) )/mg,
736	lookaheadRegExp: /^(?:[ ]*(?:(-)|(\+)|(;)|(:)) )/mg,
737
738	//http://stackoverflow.com/questions/5531899/regex-do-not-include-a-substring-within-a-group/5531972#5531972
739	//                                V~do include this if it matched
740	termRegExp: /(\n(?:(?=[ ]*[\+;:-] )|[ ]*[\+;:-]))/mg,
741	//                  ^~lookahead for this but don't include it
742	handler: function(w)
743	{
744		//if (! w.lengths) {
745		w.lengths = [0];
746		//}
747		var stack = [w.output];
748		var currLevel = 0, currType = null;
749		var listLevel, listType, itemType, baseType;
750		w.nextMatch = w.matchStart;
751		this.lookaheadRegExp.lastIndex = w.nextMatch;
752		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
753		while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
754			if(lookaheadMatch[1]) {
755				listType = "ul";
756				itemType = "li";
757			} else if(lookaheadMatch[2]) {
758				listType = "ol";
759				itemType = "li";
760			} else if(lookaheadMatch[3]) {
761				listType = "dl";
762				itemType = "dt";
763			} else if(lookaheadMatch[4]) {
764				listType = "dl";
765				itemType = "dd";
766			}
767			if(!baseType)
768				baseType = listType;
769			//fill levelstack
770			var l = lookaheadMatch[0].length
771			while ( w.lengths[w.lengths.length-1] != l ) {
772				if ( l > w.lengths[w.lengths.length-1] ) {
773					w.lengths.push(l);
774					break;
775				} else {
776					w.lengths.pop();
777				}
778			}
779			listLevel = w.lengths.length-1;
780			w.nextMatch += l;
781			var t;
782			if(listLevel > currLevel) {
783				for(t=currLevel; t<listLevel; t++) {
784					var target = (currLevel == 0) ? stack[stack.length-1] : stack[stack.length-1].lastChild;
785					stack.push(createTiddlyElement(target,listType));
786				}
787			} else if(listType!=baseType && listLevel==1) {
788				w.nextMatch -= lookaheadMatch[0].length;
789				return;
790			} else if(listLevel < currLevel) {
791				for(t=currLevel; t>listLevel; t--)
792					stack.pop();
793			} else if(listLevel == currLevel && listType != currType) {
794				stack.pop();
795				stack.push(createTiddlyElement(stack[stack.length-1].lastChild,listType));
796			}
797			currLevel = listLevel;
798			currType = listType;
799			var e = createTiddlyElement(stack[stack.length-1],itemType);
800			w.subWikifyTerm(e,this.termRegExp);
801			this.lookaheadRegExp.lastIndex = w.nextMatch;
802			lookaheadMatch = this.lookaheadRegExp.exec(w.source);
803		}
804	}
805},
806
807/*
808//array reassignment version.  I think that the up-to-6 assignments per iteration
809//could have worse performance that resizing the array.
810//see above for array re-sizing.
811// HTML doesn't have an inherent number scheme for header tags. Just treat
812// them as unnumbered for now.
813{
814	name: 't2tNumberedHeading',
815	match: '^ *\\+{1,6}[^\\+\n]',
816	lookaheadRegExp: / *(\+{1,6})([^\+\n][^\n]*[^\+\n])\1[ \t]*$/mg,
817	handler: function(w)
818	{
819		if (! w.numheading) {
820			w.numheading = [0,0,0,0,0,0];
821		}
822		this.lookaheadRegExp.lastIndex = w.matchStart;
823		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
824		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
825			var text = lookaheadMatch[2];
826			var headingindex = lookaheadMatch[1].length - 1;
827			w.numheading[headingindex]++;
828			//reset the next levels down to 0
829			for(var i = headingindex + 1; i<=5; i++){
830				w.numheading[i] = 0;
831			}
832			text = " " + text;
833			for (headingindex; headingindex >= 0; headingindex--) {
834				text = w.numheading[headingindex] + "." + text;
835			}
836			createTiddlyElement(w.output,'h'+lookaheadMatch[1].length,null,null,text);
837			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
838		} else {
839			w.output.appendChild(document.createTextNode(w.matchText));
840		}
841	}
842},
843*/
844
845// t2t prepends TABs on lines that form blockquotes.
846// Consecutive lines of the same depth of tabs are in the same block.
847// This is just like tiddly markup, only they use angle brackets.
848// Thus, I am ripping this code from a 2.6.1 formatters.
849{
850	name: 't2tQuoteByLine',
851	match: '\\t+',
852	lookaheadRegExp: /^\t+/mg,
853	termRegExp: /(\n)/mg,
854	element: 'blockquote',
855	handler: function(w)
856	{
857		var stack = [w.output];
858		var currLevel = 0;
859		var newLevel = w.matchLength;
860		var t;
861		do {
862			if(newLevel > currLevel) {
863				for(t=currLevel; t<newLevel; t++)
864					stack.push(createTiddlyElement(stack[stack.length-1],this.element));
865			} else if(newLevel < currLevel) {
866				for(t=currLevel; t>newLevel; t--)
867					stack.pop();
868			}
869			currLevel = newLevel;
870			w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
871			//originally they insert linebreaks... not in t2t
872			//createTiddlyElement(stack[stack.length-1],'br');
873			//replace the newline that was consumed
874			if(config.browser.isIE) {
875				var e = document.createTextNode('\r');
876			} else {
877				var e = document.createTextNode('\n');
878			}
879			stack[stack.length-1].appendChild(e);
880			this.lookaheadRegExp.lastIndex = w.nextMatch;
881			var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
882			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
883			if(matched) {
884				newLevel = lookaheadMatch[0].length;
885				w.nextMatch += lookaheadMatch[0].length;
886			}
887		} while(matched);
888	}
889},
890
891/*
892//COPY from tiddlywiki config.formatters
893{
894	name: "macro",
895	match: "<<",
896	////don't start new macro << HERE 
897	//lookaheadRegExp: /<<([^>\s(?:<<)]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
898	lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
899	handler: function(w)
900	{
901		this.lookaheadRegExp.lastIndex = w.matchStart;
902		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
903		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
904			w.nextMatch = this.lookaheadRegExp.lastIndex;
905			invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
906		//with this modification for nondestructiveness.
907		} else {
908			w.output.appendChild(document.createTextNode(w.matchText));
909		}
910	}
911},
912*/
913
914
915];
916
917t2tReuse = function(name)
918{
919	var i;
920	for (i = 0; i < config.formatters.length; i++) {
921		if (name == config.formatters[i].name)
922			return config.formatters[i];
923	}
924	return null;
925			
926};
927
928//attach reused formatters from standard config.formatters.
929config.t2tFormatters.push(t2tReuse("macro"));
930config.t2tFormatters.push(t2tReuse("wikiLink"));
931config.t2tFormatters.push(t2tReuse("urlLink"));
932config.t2tFormatters.push(t2tReuse("htmlEntitiesEncoding"));
933//config.t2tFormatters.push(t2tReuse("mdash"));
934config.t2tFormatters.push(t2tReuse("table"));
935
936/*
937var text = "t2tFormatters:\n";
938for (var i=0; i < config.t2tFormatters.length; i++)
939	text = text + config.t2tFormatters[i].name + "\n";
940alert(text);
941*/
942
943config.parsers.t2tFormatter = new Formatter(config.t2tFormatters);
944
945config.parsers.t2tFormatter.format = 't2t';
946config.parsers.t2tFormatter.formatTag = 't2t';
947} // end of 'install only once'
948//}}}
949/***
950vim: ft=javascript
951***/
952