Remove the old parser code

Thus introducing a few functional regressions, but it's going to be
easier to fix things up without the old code knocking around and
getting in the way.
This commit is contained in:
Jeremy Ruston 2012-12-28 22:08:32 +00:00
parent d6e531e87c
commit b006cf163f
167 changed files with 138 additions and 120412 deletions

1
bld.sh
View File

@ -12,7 +12,6 @@ node ../../tiddlywiki.js \
--verbose \
--password password \
--savetiddler ReadMe ../../readme.md text/html \
--newsavetiddler $:/core/templates/new.tiddlywiki5.template.html ../../../jermolene.github.com/new.index.html text/plain \
--savetiddler $:/core/templates/tiddlywiki5.template.html ../../../jermolene.github.com/index.html text/plain \
--savetiddler $:/core/templates/tiddlywiki5.encrypted.template.html ../../../jermolene.github.com/encrypted.html text/plain \
--savetiddler $:/core/templates/static.template.html ../../../jermolene.github.com/static.html text/plain \

View File

@ -1,44 +0,0 @@
/*\
title: $:/core/modules/commands/newsavetiddler.js
type: application/javascript
module-type: command
Command to save a tiddler to a file
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "newsavetiddler",
synchronous: false
};
var Command = function(params,commander,callback) {
this.params = params;
this.commander = commander;
this.callback = callback;
};
Command.prototype.execute = function() {
if(this.params.length < 2) {
return "Missing filename";
}
var self = this,
fs = require("fs"),
path = require("path"),
title = this.params[0],
filename = this.params[1],
type = this.params[2] || "text/html";
fs.writeFile(filename,this.commander.wiki.new_renderTiddler(type,title),"utf8",function(err) {
self.callback(err);
});
return null;
};
exports.Command = Command;
})();

View File

@ -32,14 +32,8 @@ Command.prototype.execute = function() {
path = require("path"),
title = this.params[0],
filename = this.params[1],
type = this.params[2] || "text/html",
options = {},
t;
for(t=3; t<this.params.length; t++) {
options["with"] = options["with"] || [];
options["with"][t-2] = this.params[t];
}
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title,options),"utf8",function(err) {
type = this.params[2] || "text/html";
fs.writeFile(filename,this.commander.wiki.renderTiddler(type,title),"utf8",function(err) {
self.callback(err);
});
return null;

View File

@ -1,80 +0,0 @@
/*\
title: $:/core/modules/dependencies.js
type: application/javascript
module-type: global
Represents the dependencies of a tiddler or a parser node as these fields:
tiddlers: A hashmap of explicitly tiddler titles, with the value `false` if the dependency is skinny, and `true` if it is fat
dependentAll: True if there is an implicit skinny dependency on all available tiddlers
dependentOnContextTiddler: True if the node has a fat dependency on the current context tiddler
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Dependencies = function(skinnyTiddlers,fatTiddlers,dependentAll) {
var t,title;
this.tiddlers = {};
this.dependentAll = dependentAll;
if(skinnyTiddlers) {
for(t=0; t<skinnyTiddlers.length; t++) {
title = skinnyTiddlers[t];
if(typeof title === "string" && title !== "") {
this.tiddlers[title] = false;
}
}
}
if(fatTiddlers) {
for(t=0; t<fatTiddlers.length; t++) {
title = fatTiddlers[t];
if(typeof title === "string" && title !== "") {
this.tiddlers[title] = true;
}
}
}
};
/*
Adds a dependency to a given tiddler. Note how setting a dependency of fat=false on a tiddler that already has
a dependency of fat=true will leave the fat setting as true
*/
Dependencies.prototype.addDependency = function(tiddlerTitle,fat) {
if(!this.tiddlers[tiddlerTitle]) {
this.tiddlers[tiddlerTitle] = fat;
}
};
Dependencies.prototype.mergeDependencies = function(dep) {
this.dependentAll = dep.dependentAll || this.dependentAll;
for(var t in dep.tiddlers) {
this.addDependency(t,dep.tiddlers[t]);
}
};
/*
Determine if these dependencies are impacted by the specified array of changes
changes: Hashmap of {modified: bool, deleted: bool}
contextTiddlerTitle: The title of the current context tiddler
*/
Dependencies.prototype.hasChanged = function(changes,contextTiddlerTitle) {
if(this.dependentAll) {
return true;
}
if(!!this.dependentOnContextTiddler && contextTiddlerTitle && changes.hasOwnProperty(contextTiddlerTitle)) {
return true;
}
for(var c in changes) {
if($tw.utils.hop(this.tiddlers,c)) {
return true;
}
}
return false;
};
exports.Dependencies = Dependencies;
})();

View File

@ -1,100 +0,0 @@
/*\
title: $:/core/modules/macros/button.js
type: application/javascript
module-type: macro
Button macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "button",
params: {
message: {byName: "default", type: "text"},
param: {byName: true, type: "text"},
set: {byName: true, type: "tiddler"},
setTo: {byName: true, type: "text"},
popup: {byName: true, type: "tiddler"},
hover: {byName: true, type: "text"},
qualifyTiddlerTitles: {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.dispatchMessage = function(event) {
var buttonEvent = document.createEvent("Event");
buttonEvent.initEvent("tw-" + this.params.message,true,true);
buttonEvent.param = this.params.param;
buttonEvent.tiddlerTitle = this.tiddlerTitle;
event.target.dispatchEvent(buttonEvent);
};
exports.triggerPopup = function(event) {
$tw.popup.triggerPopup({
textRef: this.params.popup,
domNode: this.child.domNode,
qualifyTiddlerTitles: this.params.qualifyTiddlerTitles,
contextTiddlerTitle: this.tiddlerTitle,
contextParents: this.parents,
wiki: this.wiki
});
};
exports.setTiddler = function() {
var set = this.params.set,
setTo = this.params.setTo,
tiddler = this.wiki.getTiddler(set);
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: set, text: setTo}));
};
exports.handleEvent = function(event) {
if(event.type === "click") {
if(this.hasParameter("message")) {
this.dispatchMessage(event);
}
if(this.hasParameter("popup")) {
this.triggerPopup(event);
}
if(this.hasParameter("set") && this.hasParameter("setTo")) {
this.setTiddler();
}
event.preventDefault();
return false;
}
if(event.type === "mouseover" || event.type === "mouseout") {
if(this.hasParameter("popup")) {
this.triggerPopup(event);
}
event.preventDefault();
return false;
}
return true;
};
exports.executeMacro = function() {
var attributes = {"class": []};
if(this.hasParameter("class")) {
$tw.utils.pushTop(attributes["class"],this.params["class"].split(" "));
}
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
var events = ["click"];
if(this.hasParameter("hover") && this.params.hover === "yes") {
events.push("mouseover","mouseout");
}
return $tw.Tree.Element("button",attributes,this.content,{
events: events,
eventHandler: this
});
};
})();

View File

@ -1,106 +0,0 @@
/*\
title: $:/core/modules/macros/checkbox.js
type: application/javascript
module-type: macro
Checkbox macro
{{{
<<checkbox tag:done>>
<<checkbox tiddler:HelloThere tag:red>>
<<checkbox tag:done><
<<view title>>
>>
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "checkbox",
params: {
tiddler: {byName: true, type: "tiddler"},
tag: {byPos: 0, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.getValue = function() {
var tiddler = this.wiki.getTiddler(this.targetTitle);
return tiddler ? tiddler.hasTag(this.params.tag) : false;
};
exports.executeMacro = function() {
// Get the title of the target tiddler
if(this.hasParameter("tiddler")) {
this.targetTitle = this.params.tiddler;
} else {
this.targetTitle = this.tiddlerTitle;
}
// Checkbox attributes
var checkboxAttributes = {
type: "checkbox"
};
if(this.getValue()) {
checkboxAttributes.checked = "true";
}
// Label attributes
var labelAttributes = {
"class": []
};
if(this.hasParameter("class")) {
$tw.utils.pushTop(labelAttributes["class"],this.params["class"].split(" "));
}
if(this.classes) {
$tw.utils.pushTop(labelAttributes["class"],this.classes);
}
// Execute content
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
// Create elements
return $tw.Tree.Element("label",labelAttributes,[
$tw.Tree.Element("input",checkboxAttributes,[],{
events: ["change"],
eventHandler: this
}),
$tw.Tree.Element("span",{},this.content)
],{});
return ;
};
exports.handleEvent = function(event) {
if(event.type === "change") {
var checked = this.child.children[0].domNode.checked,
tiddler = this.wiki.getTiddler(this.targetTitle);
if(tiddler && tiddler.hasTag(this.params.tag) !== checked) {
var newTags = tiddler.fields.tags.slice(0),
pos = newTags.indexOf(this.params.tag);
if(pos !== -1) {
newTags.splice(pos,1);
}
if(checked) {
newTags.push(this.params.tag);
}
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{tags: newTags}));
}
}
};
exports.refreshInDom = function(changes) {
// Only change the checkbox if the tiddler has changed
if(this.dependencies.hasChanged(changes,this.targetTitle)) {
this.child.children[0].domNode.checked = this.getValue();
}
// Refresh any children
this.child.refreshInDom(changes);
};
})();

View File

@ -1,40 +0,0 @@
/*\
title: $:/core/modules/macros/color.js
type: application/javascript
module-type: macro
Color macro.
Applies the specified colour to its content. By default, the colour value is obtained from the `color` field of the current tiddler
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "color",
params: {
"default": {byName: "default", type: "text"}
}
};
exports.executeMacro = function() {
var tiddler = this.wiki.getTiddler(this.tiddlerTitle),
attributes = {
style: {
"background-color": (tiddler && tiddler.fields.color) || this.params["default"]
}
};
if(this.classes) {
attributes["class"] = this.classes.slice(0);
}
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
return $tw.Tree.Element("span",attributes,this.content);
};
})();

View File

@ -1,25 +0,0 @@
/*\
title: $:/core/modules/macros/comment.js
type: application/javascript
module-type: macro
Comment macro, a no-op
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "!",
params: {}
};
exports.executeMacro = function() {
return null;
};
})();

View File

@ -1,27 +0,0 @@
/*\
title: $:/core/modules/macros/echo.js
type: application/javascript
module-type: macro
Echo macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "echo",
params: {
text: {byPos: 0, type: "text"}
}
};
exports.executeMacro = function() {
return $tw.Tree.Text(this.params.text);
};
})();

View File

@ -1,84 +0,0 @@
/*\
title: $:/core/modules/macros/edit/edit.js
type: application/javascript
module-type: macro
Edit macro for editting fields and tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "edit",
params: {
tiddler: {byName: true, type: "tiddler"},
field: {byPos: 0, type: "text"},
type: {byName: true, type: "text"},
"default": {byName: true, type: "text"},
requireFocus: {byName: true, type: "text"}
}
};
exports.evaluateDependencies = function() {
var dependencies = new $tw.Dependencies();
if(!this.srcParams.tiddler) {
dependencies.dependentOnContextTiddler = true;
}
for(var m in this.info.params) {
var paramInfo = this.info.params[m];
if(m in this.srcParams && paramInfo.type === "tiddler") {
if(typeof this.srcParams[m] === "function") {
dependencies.dependentAll = true;
} else {
dependencies.addDependency(this.srcParams[m],!paramInfo.skinny);
}
}
}
return dependencies;
};
exports.executeMacro = function() {
// Get the tiddler being editted
this.editField = this.hasParameter("field") ? this.params.field : "text";
this.editTiddler = this.hasParameter("tiddler") ? this.params.tiddler : this.tiddlerTitle;
var tiddler = this.wiki.getTiddler(this.editTiddler),
Editor;
// Figure out which editor to use
// TODO: Tiddler field modules should be able to specify a field type from which the editor is derived
if(this.editField === "text" && tiddler && tiddler.fields.type) {
Editor = this.wiki.macros.edit.editors[tiddler.fields.type];
}
if(!Editor) {
Editor = this.wiki.macros.edit.editors["text/vnd.tiddlywiki"];
}
this.editor = new Editor(this);
// Call the editor to generate the child nodes
var child = this.editor.getChild();
child.execute(this.parents,this.tiddlerTitle);
return child;
};
exports.postRenderInDom = function() {
if(this.editor.postRenderInDom) {
this.editor.postRenderInDom();
}
};
exports.refreshInDom = function(changes) {
var t;
// Only refresh if a dependency is triggered
if(this.dependencies.hasChanged(changes,this.tiddlerTitle)) {
if(this.editor.refreshInDom) {
this.editor.refreshInDom();
}
} else {
// Refresh any children
this.child.refreshInDom(changes);
}
};
})();

View File

@ -1,164 +0,0 @@
/*\
title: $:/core/modules/macros/edit/editors/bitmapeditor.js
type: application/javascript
module-type: editor
An editor module for editting bitmaps
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function BitmapEditor(macroNode) {
this.macroNode = macroNode;
}
BitmapEditor.prototype.getChild = function() {
return $tw.Tree.Element("canvas",{
"class": ["tw-edit-field"]
},[],{
events: ["touchstart","touchmove","touchend","mousedown","mousemove","mouseup"],
eventHandler: this
});
};
BitmapEditor.prototype.postRenderInDom = function() {
var tiddler = this.macroNode.wiki.getTiddler(this.macroNode.editTiddler),
canvas = this.macroNode.child.domNode,
currImage = new Image();
///////////////////// // Set the macro node itself to be position: relative
///////////////////// this.macroNode.domNode.style.position = "relative";
// Get the current bitmap into an image object
currImage.src = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
// Copy it to the on-screen canvas
canvas.width = currImage.width;
canvas.height = currImage.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(currImage,0,0);
// And also copy the current bitmap to the off-screen canvas
this.currCanvas = document.createElement("canvas");
this.currCanvas.width = currImage.width;
this.currCanvas.height = currImage.height;
ctx = this.currCanvas.getContext("2d");
ctx.drawImage(currImage,0,0);
};
BitmapEditor.prototype.handleEvent = function(event) {
switch(event.type) {
case "touchstart":
this.brushDown = true;
this.strokeStart(event.touches[0].clientX,event.touches[0].clientY);
event.preventDefault();
event.stopPropagation();
return false;
case "touchmove":
if(this.brushDown) {
this.strokeMove(event.touches[0].clientX,event.touches[0].clientY);
}
event.preventDefault();
event.stopPropagation();
return false;
case "touchend":
if(this.brushDown) {
this.brushDown = false;
this.strokeEnd();
}
event.preventDefault();
event.stopPropagation();
return false;
case "mousedown":
this.strokeStart(event.clientX,event.clientY);
this.brushDown = true;
event.preventDefault();
event.stopPropagation();
return false;
case "mousemove":
if(this.brushDown) {
this.strokeMove(event.clientX,event.clientY);
event.preventDefault();
event.stopPropagation();
return false;
}
return true;
case "mouseup":
if(this.brushDown) {
this.brushDown = false;
this.strokeEnd();
event.preventDefault();
event.stopPropagation();
return false;
}
return true;
}
return true;
};
BitmapEditor.prototype.adjustCoordinates = function(x,y) {
var canvas = this.macroNode.child.domNode,
canvasRect = canvas.getBoundingClientRect(),
scale = canvas.width/canvasRect.width;
return {x: (x - canvasRect.left) * scale, y: (y - canvasRect.top) * scale};
};
BitmapEditor.prototype.strokeStart = function(x,y) {
// Start off a new stroke
this.stroke = [this.adjustCoordinates(x,y)];
};
BitmapEditor.prototype.strokeMove = function(x,y) {
var canvas = this.macroNode.child.domNode,
ctx = canvas.getContext("2d"),
t;
// Add the new position to the end of the stroke
this.stroke.push(this.adjustCoordinates(x,y));
// Redraw the previous image
ctx.drawImage(this.currCanvas,0,0);
// Render the stroke
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.beginPath();
ctx.moveTo(this.stroke[0].x,this.stroke[0].y);
for(t=1; t<this.stroke.length-1; t++) {
var s1 = this.stroke[t],
s2 = this.stroke[t-1],
tx = (s1.x + s2.x)/2,
ty = (s1.y + s2.y)/2;
ctx.quadraticCurveTo(s2.x,s2.y,tx,ty);
}
ctx.stroke();
};
BitmapEditor.prototype.strokeEnd = function() {
// Copy the bitmap to the off-screen canvas
var canvas = this.macroNode.child.domNode,
ctx = this.currCanvas.getContext("2d");
ctx.drawImage(canvas,0,0);
// Save the image into the tiddler
this.saveChanges();
};
BitmapEditor.prototype.saveChanges = function() {
var tiddler = this.macroNode.wiki.getTiddler(this.macroNode.editTiddler);
if(tiddler) {
// data URIs look like "data:<type>;base64,<text>"
var dataURL = this.macroNode.child.domNode.toDataURL(tiddler.fields.type,1.0),
posColon = dataURL.indexOf(":"),
posSemiColon = dataURL.indexOf(";"),
posComma = dataURL.indexOf(","),
type = dataURL.substring(posColon+1,posSemiColon),
text = dataURL.substring(posComma+1);
var update = {type: type, text: text};
this.macroNode.wiki.addTiddler(new $tw.Tiddler(tiddler,update));
}
};
exports["image/jpg"] = BitmapEditor;
exports["image/jpeg"] = BitmapEditor;
exports["image/png"] = BitmapEditor;
exports["image/gif"] = BitmapEditor;
})();

View File

@ -1,151 +0,0 @@
/*\
title: $:/core/modules/macros/edit/editors/texteditor.js
type: application/javascript
module-type: editor
An editor module for editting text
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var MIN_TEXT_AREA_HEIGHT = 100;
function TextEditor(macroNode) {
this.macroNode = macroNode;
}
/*
Get the tiddler being editted, field name and current value
*/
TextEditor.prototype.getEditText = function() {
// Get the current tiddler and the field name
var tiddler = this.macroNode.wiki.getTiddler(this.macroNode.editTiddler),
value;
// If we've got a tiddler, the value to display is the field string value
if(tiddler) {
value = tiddler.getFieldString(this.macroNode.editField);
} else {
// Otherwise, we need to construct a default value for the editor
if(this.macroNode.hasParameter("default")) {
value = this.macroNode.params["default"];
} else {
switch(this.macroNode.editField) {
case "text":
value = "Type the text for the tiddler '" + this.macroNode.editTiddler + "'";
break;
case "title":
value = this.macroNode.editTiddler;
break;
default:
value = "";
break;
}
}
}
return {tiddler: tiddler, field: this.macroNode.editField, value: value};
};
TextEditor.prototype.getChild = function() {
var edit = this.getEditText();
var attributes = {
"class": ["tw-edit-field"]
},
tagName,
content = [];
if(this.macroNode.classes) {
$tw.utils.pushTop(attributes["class"],this.macroNode.classes);
}
// Figure out what element to use for this editor
var type = this.macroNode.params.type;
if(type === undefined) {
type = edit.field === "text" ? "textarea" : "input";
}
switch(type) {
case "textarea":
tagName = "textarea";
content.push($tw.Tree.Text(edit.value));
break;
case "search":
tagName = "input";
attributes.type = "search";
attributes.value = edit.value;
break;
default: // "input"
tagName = "input";
attributes.type = "text";
attributes.value = edit.value;
break;
}
// Wrap the editor control in a div
return $tw.Tree.Element(this.macroNode.isBlock ? "div" : "span",{},[$tw.Tree.Element(tagName,attributes,content,{
events: ["focus","blur","keyup"],
eventHandler: this
})]);
};
TextEditor.prototype.handleEvent = function(event) {
// Get the value of the field if it might have changed
if("keyup focus blur".split(" ").indexOf(event.type) !== -1) {
this.saveChanges();
}
// Fix the height of the textarea if required
if("keyup focus".split(" ").indexOf(event.type) !== -1) {
var self = this;
window.setTimeout(function() {
self.fixHeight();
},5);
}
return true;
};
TextEditor.prototype.saveChanges = function() {
var text = this.macroNode.child.children[0].domNode.value,
tiddler = this.macroNode.wiki.getTiddler(this.macroNode.editTiddler);
// if(this.macroNode.params.requireFocus === "yes" && document.activeElement !== this.macroNode.child.children[0].domNode) {
// text = this.macroNode.params["default"] || "";
// }
if(!tiddler) {
tiddler = new $tw.Tiddler({title: this.macroNode.editTiddler});
}
if(text !== tiddler.fields[this.macroNode.editField]) {
var update = {};
update[this.macroNode.editField] = text;
this.macroNode.wiki.addTiddler(new $tw.Tiddler(tiddler,update));
}
};
TextEditor.prototype.fixHeight = function() {
if(this.macroNode.child && this.macroNode.child.children[0] && this.macroNode.child.children[0].type === "textarea") {
var wrapper = this.macroNode.child.domNode,
textarea = this.macroNode.child.children[0].domNode;
// Set the text area height to 1px temporarily, which allows us to read the true scrollHeight
var prevWrapperHeight = wrapper.style.height;
wrapper.style.height = textarea.style.height + "px";
textarea.style.overflow = "hidden";
textarea.style.height = "1px";
textarea.style.height = Math.max(textarea.scrollHeight,MIN_TEXT_AREA_HEIGHT) + "px";
wrapper.style.height = prevWrapperHeight;
}
};
TextEditor.prototype.postRenderInDom = function() {
this.fixHeight();
};
TextEditor.prototype.refreshInDom = function() {
if(document.activeElement !== this.macroNode.child.children[0].domNode) {
var edit = this.getEditText();
this.macroNode.child.children[0].domNode.value = edit.value;
}
// Fix the height if needed
this.fixHeight();
};
exports["text/vnd.tiddlywiki"] = TextEditor;
exports["text/plain"] = TextEditor;
})();

View File

@ -1,66 +0,0 @@
/*\
title: $:/core/modules/macros/fields.js
type: application/javascript
module-type: macro
Fields macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "fields",
dependentOnContextTiddler: true,
params: {
}
};
exports.executeMacro = function() {
// Create the table
var attributes = {
"class": ["tw-fields-table"]
};
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
var rows = [
$tw.Tree.Element("tr",{},[
$tw.Tree.Element("th",{},[$tw.Tree.Text("Field")]),
$tw.Tree.Element("th",{},[$tw.Tree.Text("Value")])
])
];
// Get the value to display
var tiddler = this.wiki.getTiddler(this.tiddlerTitle);
if(tiddler) {
var fields = [];
for(var f in tiddler.fields) {
fields.push(f);
}
fields.sort();
for(f=0; f<fields.length; f++) {
var value;
if(fields[f] === "text") {
value = $tw.Tree.Element("em",{},[
$tw.Tree.Text("(length: " + tiddler.fields.text.length + ")")
]);
} else {
value = $tw.Tree.Text(tiddler.getFieldString(fields[f]));
}
rows.push($tw.Tree.Element("tr",{},[
$tw.Tree.Element("td",{},[$tw.Tree.Text(fields[f])]),
$tw.Tree.Element("td",{},[value])
]));
}
}
var child = $tw.Tree.Element("table",attributes,[
$tw.Tree.Element("tbody",{},rows)
]);
child.execute(this.parents,this.tiddlerTitle);
return child;
};
})();

View File

@ -1,55 +0,0 @@
/*\
title: $:/core/modules/macros/image.js
type: application/javascript
module-type: macro
Image macro for displaying images
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "image",
params: {
src: {byName: "default", type: "tiddler"},
text: {byName: true, type: "text"},
alignment: {byName: true, type: "text"},
width: {byName: true, type: "text"},
height: {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
if(this.wiki.tiddlerExists(this.params.src)) {
var imageTree = this.wiki.parseTiddler(this.params.src).tree,
cloneImage = imageTree[0].clone();
if(this.hasParameter("width")) {
cloneImage.attributes.width = this.params.width;
}
if(this.hasParameter("height")) {
cloneImage.attributes.height = this.params.height;
}
if(this.params.text) {
return $tw.Tree.Element("div",{
alt: this.params.text,
title: this.params.text
},[cloneImage]);
} else {
return cloneImage;
}
} else {
return $tw.Tree.Element("img",{
src: this.params.src,
alt: this.params.text,
width: this.params.width,
height: this.params.height,
title: this.params.text
});
}
};
})();

View File

@ -1,117 +0,0 @@
/*\
title: $:/core/modules/macros/link.js
type: application/javascript
module-type: macro
Implements the link macro.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var isLinkExternal = function(to) {
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
return externalRegExp.test(to);
};
exports.info = {
name: "link",
params: {
to: {byName: "default", type: "tiddler", skinny: true},
throughField: {byname: true, type: "text"},
space: {byName: true, type: "text"},
qualifyHoverTitle: {byName: true, type: "text"},
hover: {byName: true, type: "tiddler"}
}
};
exports.handleEvent = function (event) {
if(event.type === "click") {
if(isLinkExternal(this.linkInfo.to)) {
event.target.setAttribute("target","_blank");
return true;
} else {
var navEvent = document.createEvent("Event");
navEvent.initEvent("tw-navigate",true,true);
navEvent.navigateTo = this.linkInfo.to;
navEvent.navigateFromNode = this;
navEvent.navigateFromClientRect = this.child.domNode.getBoundingClientRect();
event.target.dispatchEvent(navEvent);
event.preventDefault();
return false;
}
}
if(event.type === "mouseover" || event.type === "mouseout") {
if(this.hasParameter("hover")) {
$tw.popup.triggerPopup({
textRef: this.params.hover,
domNode: this.child.domNode,
qualifyTiddlerTitles: this.params.qualifyHoverTitle,
contextTiddlerTitle: this.tiddlerTitle,
contextParents: this.parents,
wiki: this.wiki
});
}
event.preventDefault();
return false;
}
};
exports.executeMacro = function() {
// Assemble the information about the link
this.linkInfo = {
space: this.params.space
};
if(this.hasParameter("to")) {
this.linkInfo.to = this.params.to;
} else if(this.hasParameter("throughField") && this.tiddlerTitle) {
var currTiddler = this.wiki.getTiddler(this.tiddlerTitle);
if(currTiddler && this.params.throughField in currTiddler.fields) {
this.linkInfo.to = currTiddler.fields[this.params.throughField];
}
}
// Generate the default link characteristics
this.linkInfo.isExternal = isLinkExternal(this.linkInfo.to);
if(!this.linkInfo.isExternal) {
this.linkInfo.isMissing = !this.wiki.tiddlerExists(this.linkInfo.to);
}
this.linkInfo.attributes = {
href: this.linkInfo.to
};
if(!this.linkInfo.isExternal) {
this.linkInfo.attributes.href = encodeURIComponent(this.linkInfo.to);
}
// Generate the default classes for the link
this.linkInfo.attributes["class"] = ["tw-tiddlylink"];
if(this.linkInfo.isExternal) {
this.linkInfo.attributes["class"].push("tw-tiddlylink-external");
} else {
this.linkInfo.attributes["class"].push("tw-tiddlylink-internal");
if(this.linkInfo.isMissing) {
this.linkInfo.attributes["class"].push("tw-tiddlylink-missing");
} else {
this.linkInfo.attributes["class"].push("tw-tiddlylink-resolves");
}
}
if(this.classes) {
$tw.utils.pushTop(this.linkInfo.attributes["class"],this.classes);
}
// Create the link
var events = ["click"];
if(this.hasParameter("hover")) {
events.push("mouseover","mouseout");
}
var child;
if(this.linkInfo.suppressLink) {
child = $tw.Tree.Element("span",{},this.content);
} else {
child = $tw.Tree.Element("a",this.linkInfo.attributes,this.content,{events: events, eventHandler: this});
}
child.execute(this.parents,this.tiddlerTitle);
return child;
};
})();

View File

@ -1,317 +0,0 @@
/*\
title: $:/core/modules/macros/list.js
type: application/javascript
module-type: macro
List macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "list",
dependentAll: true, // Tiddlers containing <<list>> macro are dependent on every tiddler
params: {
type: {byPos: 0, type: "text"},
filter: {byName: true, type: "filter"},
history: {byName: true, type: "tiddler"},
template: {byName: true, type: "tiddler"},
editTemplate: {byName: true, type: "tiddler"},
emptyMessage: {byName: true, type: "text"},
listviewTiddler: {byName: true, type: "tiddler"},
listview: {byName: true, type: "text"},
itemClass: {byName: true, type: "text"},
map: {byName: true, type: "tiddler"},
block: {ByName: true, type: "text"} // HACK: To be removed...
}
};
/*
These types are shorthands for particular filters
*/
var typeMappings = {
all: "[!is[shadow]sort[title]]",
recent: "[!is[shadow]sort[modified]]",
missing: "[is[missing]sort[title]]",
orphans: "[is[orphan]sort[title]]",
shadowed: "[is[shadow]sort[title]]"
};
exports.executeMacro = function() {
this.useBlock = this.isBlock;
if(this.hasParameter("block")) {
this.useBlock = this.params.block === "yes";
}
// Get the list of tiddlers object
this.getTiddlerList();
// Create the list frame element
var attributes = {"class": ["tw-list-frame"]};
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
this.listFrame = $tw.Tree.Element(this.useBlock ? "div" : "span",attributes,[]);
// Create the list
if(this.list.length === 0) {
// Check for an empty list
this.listFrame.children = [this.getEmptyMessage()];
} else {
// Create the list
for(var t=0; t<this.list.length; t++) {
this.listFrame.children.push(this.createListElement(this.list[t]));
}
}
return this.listFrame;
};
exports.postRenderInDom = function() {
this.listview = this.chooseListView();
this.history = [];
};
/*
Select the appropriate list viewer
*/
exports.chooseListView = function() {
// Instantiate the list view
var listviewName;
if(this.hasParameter("listviewTiddler")) {
listviewName = this.wiki.getTextReference(this.params.listviewTiddler);
}
if(!listviewName && this.hasParameter("listview")) {
listviewName = this.params.listview;
}
var ListView = this.wiki.macros.list.listviews[listviewName];
return ListView ? new ListView(this) : null;
};
exports.getTiddlerList = function() {
var filter;
if(this.hasParameter("type")) {
filter = typeMappings[this.params.type];
} else if(this.hasParameter("filter")) {
filter = this.params.filter;
}
if(!filter) {
filter = "[!is[shadow]]";
}
this.list = this.wiki.filterTiddlers(filter,this.tiddlerTitle);
};
/*
Create and execute the nodes representing the empty message
*/
exports.getEmptyMessage = function() {
var nodes = this.wiki.parseText("text/vnd.tiddlywiki",this.params.emptyMessage).tree;
for(var c=0; c<nodes.length; c++) {
nodes[c].execute(this.parents,this.tiddlerTitle);
}
return $tw.Tree.Element("span",{},nodes);
};
/*
Create a list element representing a given tiddler
*/
exports.createListElement = function(title) {
var node = this.createListElementMacro(title),
attributes = {"class": ["tw-list-element"]},
eventHandler = {handleEvent: function(event) {
// Add context information to the event
event.navigateFromTitle = title;
return true;
}};
node.execute(this.parents,this.tiddlerTitle);
// Add any specified classes
if(this.hasParameter("itemClass")) {
attributes["class"].push(this.params.itemClass);
}
var listElement = $tw.Tree.Element(this.useBlock ? "div" : "span",attributes,[node],{
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-CloseTiddler","tw-NewTiddler"],
eventHandler: eventHandler
});
// Save our data inside the list element node
listElement.listElementInfo = {title: title};
return listElement;
};
/*
Create the tiddler macro needed to represent a given tiddler
*/
exports.createListElementMacro = function(title) {
// Check if the tiddler is a draft
var tiddler = this.wiki.getTiddler(title),
isDraft = tiddler ? tiddler.hasField("draft.of") : false;
// Figure out the template to use
var template = this.params.template,
templateTree = undefined;
if(isDraft && this.hasParameter("editTemplate")) {
template = this.params.editTemplate;
}
// Check for not having a template
if(!template) {
if(this.content.length > 0) {
// Use our content as the template
templateTree = [];
for(var t=0; t<this.content.length; t++) {
templateTree.push(this.content[t].clone());
}
} else {
// Use default content
var defaultTemplate = "<<view title link>>";
templateTree = this.wiki.parseText("text/vnd.tiddlywiki",defaultTemplate).tree;
}
}
// Create the tiddler macro
return $tw.Tree.Macro("tiddler",{
srcParams: {
target: title,
template: template
},
wiki: this.wiki,
content: templateTree
});
};
/*
Remove a list element from the list, along with the attendant DOM nodes
*/
exports.removeListElement = function(index) {
// Get the list element
var listElement = this.listFrame.children[index];
// Invoke the listview to animate the removal
if(this.listview && this.listview.remove) {
if(!this.listview.remove(index)) {
// Only delete the DOM element if the listview.remove() returned false
listElement.domNode.parentNode.removeChild(listElement.domNode);
}
} else {
// Always remove the DOM node if we didn't invoke the listview
listElement.domNode.parentNode.removeChild(listElement.domNode);
}
// Then delete the actual renderer node
this.listFrame.children.splice(index,1);
};
/*
Return the index of the list element that corresponds to a particular title
startIndex: index to start search (use zero to search from the top)
title: tiddler title to seach for
*/
exports.findListElementByTitle = function(startIndex,title) {
while(startIndex < this.listFrame.children.length) {
var listElementInfo = this.listFrame.children[startIndex].listElementInfo;
if(listElementInfo && listElementInfo.title === title) {
return startIndex;
}
startIndex++;
}
return undefined;
};
/*
Selectively update the list in response to changes in tiddlers
*/
exports.refreshInDom = function(changes) {
// If any of our parameters have changed we'll have to completely re-execute the macro
var paramNames = ["template","editTemplate"];
for(var t=0; t<paramNames.length; t++) {
if(this.hasParameter(paramNames[t]) && $tw.utils.hop(changes,this.params[paramNames[t]])) {
this.reexecuteInDom();
return;
}
}
// Reflect any changes in the list
this.handleListChanges(changes);
// Process any history list changes
if(this.hasParameter("history") && $tw.utils.hop(changes,this.params.history)) {
this.handleHistoryChanges();
}
};
/*
Handle changes to the content of the list
*/
exports.handleListChanges = function(changes) {
// Get the list of tiddlers, saving the previous length
var t,
prevListLength = this.list.length;
this.getTiddlerList();
// Check if the list is empty
if(this.list.length === 0) {
// Check if it was empty before
if(prevListLength === 0) {
// If so, just refresh the empty message
this.listFrame.refreshInDom(changes);
return;
} else {
// If the list wasn't empty before, empty it
for(t=prevListLength-1; t>=0; t--) {
this.removeListElement(t);
}
// Insert the empty message
this.listFrame.children = [this.getEmptyMessage()];
this.listFrame.children[0].renderInDom(this.listFrame.domNode,this.listFrame.domNode.childNodes[0]);
return;
}
} else {
// If it is not empty now, but was empty previously, then remove the empty message
if(prevListLength === 0) {
this.removeListElement(0);
}
}
// Step through the list and adjust our child list elements appropriately
for(t=0; t<this.list.length; t++) {
// Check to see if the list element is already there
var index = this.findListElementByTitle(t,this.list[t]);
if(index === undefined) {
// The list element isn't there, so we need to insert it
this.listFrame.children.splice(t,0,this.createListElement(this.list[t]));
this.listFrame.children[t].renderInDom(this.listFrame.domNode,this.listFrame.domNode.childNodes[t]);
if(this.listview && this.listview.insert) {
this.listview.insert(t);
}
} else {
// Delete any list elements preceding the one we want
if(index > t) {
for(var n=index-1; n>=t; n--) {
this.removeListElement(n);
}
}
// Refresh the node we're reusing
this.listFrame.children[t].refreshInDom(changes);
}
}
// Remove any left over elements
if(this.listFrame.children.length > this.list.length) {
for(t=this.listFrame.children.length-1; t>=this.list.length; t--) {
this.removeListElement(t);
}
}
};
/*
Handle any changes to the history list
*/
exports.handleHistoryChanges = function() {
// Get the history data
var newHistory = this.wiki.getTiddlerData(this.params.history,[]);
// Ignore any entries of the history that match the previous history
var entry = 0;
while(entry < newHistory.length && entry < this.history.length && newHistory[entry].title === this.history[entry].title) {
entry++;
}
// Navigate forwards to each of the new tiddlers
while(entry < newHistory.length) {
if(this.listview && this.listview.navigateTo) {
this.listview.navigateTo(newHistory[entry]);
}
entry++;
}
// Update the history
this.history = newHistory;
};
})();

View File

@ -1,135 +0,0 @@
/*\
title: $:/core/modules/macros/list/listviews/cecily.js
type: application/javascript
module-type: listview
Views the list through a 2D map
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function CecilyListView(listMacro) {
// The list macro we're attached to
this.listMacro = listMacro;
// Prepare the list frame
var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode;
// Position the initial list entries on the map
this.loadMap();
for(var t=0; t<listFrame.children.length; t++) {
if(listFrame.children[t].listElementInfo) {
var domNode = listFrame.children[t].domNode,
title = listFrame.children[t].listElementInfo.title;
domNode.style.position = "absolute";
this.positionTiddler(title,domNode);
}
}
}
CecilyListView.prototype.getMapTiddlerTitle = function() {
return this.listMacro.params.map || "$:/TiddlerMap";
};
CecilyListView.prototype.loadMap = function() {
this.map = this.listMacro.wiki.getTiddlerData(this.getMapTiddlerTitle(),{
positions: {},
newTiddlerPosition: {x: 0, y: 0}
});
};
CecilyListView.prototype.saveMap = function() {
this.listMacro.wiki.setTiddlerData(this.getMapTiddlerTitle(),this.map);
};
// Get the position of a particular tiddler
CecilyListView.prototype.lookupTiddlerInMap = function(title,domNode) {
// First try looking it up in the map
if(this.map.positions[title]) {
return this.map.positions[title];
}
// If the tiddler wasn't in the map we'll have to compute it
var newPosition;
switch(this.map.positionNew) {
default: // "right"
newPosition = {
x: this.map.newTiddlerPosition.x,
y: this.map.newTiddlerPosition.y,
w: 100,
h: 100
};
this.map.newTiddlerPosition.x += newPosition.w * 1.2;
break;
}
// A default position
newPosition = newPosition || {x: 0,y: 0,w: 100,h: 100};
// Save the position back to the map
this.map.positions[title] = newPosition;
this.saveMap();
return newPosition;
};
CecilyListView.prototype.positionTiddler = function(title,domNode) {
var pos = this.lookupTiddlerInMap(title,domNode),
scale = pos.w/domNode.offsetWidth;
domNode.setAttribute("data-tw-zoom",JSON.stringify(pos));
$tw.utils.setStyle(domNode,[
{transformOrigin: "0% 0%"},
{transform: "translateX(" + pos.x + "px) translateY(" + pos.y + "px) scale(" + scale + ")"}
]);
};
CecilyListView.prototype.navigateTo = function(historyInfo) {
var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title),
listElementNode = this.listMacro.listFrame.children[listElementIndex],
targetElement = listElementNode.domNode;
// Scroll the node into view
var scrollEvent = document.createEvent("Event");
scrollEvent.initEvent("tw-scroll",true,true);
targetElement.dispatchEvent(scrollEvent);
};
CecilyListView.prototype.insert = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode;
targetElement.style.position = "absolute";
$tw.utils.setStyle(targetElement,[
{transition: ""},
{opacity: "0.0"}
]);
this.positionTiddler(listElementNode.listElementInfo.title,targetElement);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-out"},
{opacity: "1.0"}
]);
};
CecilyListView.prototype.remove = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode;
// Attach an event handler for the end of the transition
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
if(targetElement.parentNode) {
targetElement.parentNode.removeChild(targetElement);
}
},false);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-out"},
{opacity: "1.0"}
]);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{opacity: "0.0"}
]);
// Returning true causes the DOM node not to be deleted
return true;
};
exports.cecily = CecilyListView;
})();

View File

@ -1,95 +0,0 @@
/*\
title: $:/core/modules/macros/list/listviews/classic.js
type: application/javascript
module-type: listview
Views the list as a linear sequence
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function ClassicListView(listMacro) {
this.listMacro = listMacro;
var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode;
}
ClassicListView.prototype.navigateTo = function(historyInfo) {
var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title),
listElementNode = this.listMacro.listFrame.children[listElementIndex],
targetElement = listElementNode.domNode;
// Scroll the node into view
var scrollEvent = document.createEvent("Event");
scrollEvent.initEvent("tw-scroll",true,true);
targetElement.dispatchEvent(scrollEvent);
};
ClassicListView.prototype.insert = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode;
// Get the current height of the tiddler
var currHeight = targetElement.offsetHeight + parseInt(window.getComputedStyle(targetElement).marginTop,10);
// Reset the margin once the transition is over
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transform: "none"},
{marginBottom: "auto"}
]);
},false);
// Set up the initial position of the element
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
$tw.utils.forceLayout(targetElement);
// Transition to the final position
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"margin-bottom " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transform: "rotateX(0deg)"},
{marginBottom: "0px"},
{opacity: "1.0"}
]);
};
ClassicListView.prototype.remove = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode;
// Get the current height of the tiddler
var currWidth = targetElement.offsetWidth,
currHeight = targetElement.offsetHeight + parseInt(window.getComputedStyle(targetElement).marginTop,10);
// Attach an event handler for the end of the transition
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
if(targetElement.parentNode) {
targetElement.parentNode.removeChild(targetElement);
}
},false);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: "none"},
{transform: "translateX(0px)"},
{marginBottom: "0px"},
{opacity: "1.0"}
]);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"opacity " + $tw.config.preferences.animationDurationMs + " ease-in-out, " +
"margin-bottom " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transform: "translateX(" + currWidth + "px)"},
{marginBottom: (-currHeight) + "px"},
{opacity: "0.0"}
]);
// Returning true causes the DOM node not to be deleted
return true;
};
exports.classic = ClassicListView;
})();

View File

@ -1,96 +0,0 @@
/*\
title: $:/core/modules/macros/list/listviews/sideways.js
type: application/javascript
module-type: listview
Views the list as a sideways linear sequence
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
function SidewaysListView(listMacro) {
this.listMacro = listMacro;
// Prepare the list frame
var listFrame = this.listMacro.listFrame,
listFrameDomNode = listFrame.domNode;
// Prepare any list elements
for(var t=0; t<this.listMacro.list.length; t++) {
var index = this.listMacro.findListElementByTitle(0,this.listMacro.list[t]);
if(index !== undefined) {
var listElement = listFrame.children[index];
$tw.utils.setStyle(listElement.domNode,[
{verticalAlign: "top"},
{display: "inline-block"}
]);
}
}
}
SidewaysListView.prototype.navigateTo = function(historyInfo) {
var listElementIndex = this.listMacro.findListElementByTitle(0,historyInfo.title),
listElementNode = this.listMacro.listFrame.children[listElementIndex],
targetElement = listElementNode.domNode;
// Scroll the node into view
var scrollEvent = document.createEvent("Event");
scrollEvent.initEvent("tw-scroll",true,true);
targetElement.dispatchEvent(scrollEvent);
};
SidewaysListView.prototype.insert = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode;
// Set up the initial position of the element
$tw.utils.setStyle(targetElement,[
{verticalAlign: "top"},
{display: "inline-block"},
{transition: "none"},
{opacity: "0.0"}
]);
var currWidth = targetElement.offsetWidth + parseInt(window.getComputedStyle(targetElement).marginLeft,10);
$tw.utils.setStyle(targetElement,[
{marginRight: (-currWidth) + "px"}
]);
$tw.utils.forceLayout(targetElement);
// Transition to the final position
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " +
"margin-right " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{opacity: "1.0"},
{marginRight: ""}
]);
};
SidewaysListView.prototype.remove = function(index) {
var listElementNode = this.listMacro.listFrame.children[index],
targetElement = listElementNode.domNode,
currWidth = targetElement.offsetWidth + parseInt(window.getComputedStyle(targetElement).marginLeft,10);
// Attach an event handler for the end of the transition
targetElement.addEventListener($tw.utils.convertEventName("transitionEnd"),function(event) {
if(targetElement.parentNode) {
targetElement.parentNode.removeChild(targetElement);
}
},false);
// Animate the closure
$tw.utils.setStyle(targetElement,[
{transition: ""},
{opacity: "1.0"},
{marginRight: "0px"}
]);
$tw.utils.forceLayout(targetElement);
$tw.utils.setStyle(targetElement,[
{transition: "opacity " + $tw.config.preferences.animationDurationMs + " ease-out, " +
"margin-right " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{opacity: "0.0"},
{marginRight: (-currWidth) + "px"}
]);
// Returning true causes the DOM node not to be deleted
return true;
};
exports.sideways = SidewaysListView;
})();

View File

@ -1,223 +0,0 @@
/*\
title: $:/core/modules/macros/navigator.js
type: application/javascript
module-type: macro
Traps navigation events to update a story tiddler and history tiddler. Can also optionally capture navigation target in a specified text reference.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "navigator",
params: {
story: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
history: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
set: {byName: true, type: "tiddler"}
}
};
exports.getList = function(title) {
var text = this.wiki.getTextReference(title,"");
if(text && text.length > 0) {
return text.split("\n");
} else {
return [];
}
};
exports.saveList = function(title,list) {
var storyTiddler = this.wiki.getTiddler(title);
this.wiki.addTiddler(new $tw.Tiddler({
title: title
},storyTiddler,{text: list.join("\n")}));
};
exports.findTitleInStory = function(title,defaultIndex) {
for(var t=0; t<this.story.length; t++) {
if(this.story[t] === title) {
return t;
}
}
return defaultIndex;
};
exports.handleEvent = function(event) {
if(this.eventMap[event.type]) {
this.eventMap[event.type].call(this,event);
}
};
exports.eventMap = {};
// Navigate to a specified tiddler
exports.eventMap["tw-navigate"] = function(event) {
if(this.hasParameter("story")) {
// Update the story tiddler if specified
this.story = this.getList(this.storyTitle);
// See if the tiddler is already there
var slot = this.findTitleInStory(event.navigateTo,-1);
// If not we need to add it
if(slot === -1) {
// First we try to find the position of the story element we navigated from
slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
// Add the tiddler
this.story.splice(slot,0,event.navigateTo);
// Save the story
this.saveList(this.storyTitle,this.story);
}
}
// Set the tiddler if specified
if(this.hasParameter("set")) {
this.wiki.setTextReference(this.params.set,event.navigateTo);
}
// Add a new record to the top of the history stack
if(this.hasParameter("history")) {
this.history = this.wiki.getTiddlerData(this.historyTitle,[]);
this.history.push({title: event.navigateTo, fromPageRect: event.navigateFromClientRect});
this.wiki.setTiddlerData(this.historyTitle,this.history);
}
event.stopPropagation();
return false;
};
// Close a specified tiddler
exports.eventMap["tw-close"] = function(event) {
this.story = this.getList(this.storyTitle);
// Look for tiddlers with this title to close
var slot = this.findTitleInStory(event.tiddlerTitle,-1);
if(slot !== -1) {
this.story.splice(slot,1);
this.saveList(this.storyTitle,this.story);
}
event.stopPropagation();
return false;
};
// Place a tiddler in edit mode
exports.eventMap["tw-EditTiddler"] = function(event) {
this.story = this.getList(this.storyTitle);
// Replace the specified tiddler with a draft in edit mode
for(var t=0; t<this.story.length; t++) {
if(this.story[t] === event.tiddlerTitle) {
// Compute the title for the draft
var draftTitle = "Draft " + (new Date()) + " of " + event.tiddlerTitle;
this.story[t] = draftTitle;
// Get the current value of the tiddler we're editing
var tiddler = this.wiki.getTiddler(event.tiddlerTitle);
// Save the initial value of the draft tiddler
this.wiki.addTiddler(new $tw.Tiddler(
{
text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
},
tiddler,
{
title: draftTitle,
"draft.title": event.tiddlerTitle,
"draft.of": event.tiddlerTitle
}));
}
}
this.saveList(this.storyTitle,this.story);
event.stopPropagation();
return false;
};
// Take a tiddler out of edit mode, saving the changes
exports.eventMap["tw-SaveTiddler"] = function(event) {
this.story = this.getList(this.storyTitle);
var storyTiddlerModified = false;
for(var t=0; t<this.story.length; t++) {
if(this.story[t] === event.tiddlerTitle) {
var tiddler = this.wiki.getTiddler(event.tiddlerTitle);
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.title")) {
// Save the draft tiddler as the real tiddler
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{
title: tiddler.fields["draft.title"],
modified: new Date(),
"draft.title": undefined,
"draft.of": undefined
}));
// Remove the draft tiddler
this.wiki.deleteTiddler(event.tiddlerTitle);
// Remove the original tiddler if we're renaming it
if(tiddler.fields["draft.of"] !== tiddler.fields["draft.title"]) {
this.wiki.deleteTiddler(tiddler.fields["draft.of"]);
}
// Make the story record point to the newly saved tiddler
this.story[t] = tiddler.fields["draft.title"];
// Check if we're modifying the story tiddler itself
if(tiddler.fields["draft.title"] === this.params.story) {
storyTiddlerModified = true;
}
}
}
}
if(!storyTiddlerModified) {
this.saveList(this.storyTitle,this.story);
}
event.stopPropagation();
return false;
};
// Create a new draft tiddler
exports.eventMap["tw-NewTiddler"] = function(event) {
// Get the story details
this.story = this.getList(this.storyTitle);
// Create the new tiddler
var title;
for(var t=0; true; t++) {
title = "New Tiddler" + (t ? " " + t : "");
if(!this.wiki.tiddlerExists(title)) {
break;
}
}
var tiddler = new $tw.Tiddler({
title: title,
text: "Newly created tiddler"
});
this.wiki.addTiddler(tiddler);
// Create the draft tiddler
var draftTitle = "New Tiddler at " + (new Date()),
draftTiddler = new $tw.Tiddler({
text: "Type the text for the new tiddler",
title: draftTitle,
"draft.title": title,
"draft.of": title
});
this.wiki.addTiddler(draftTiddler);
// Update the story to insert the new draft at the top
var slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
this.story.splice(slot,0,draftTitle);
// Save the updated story
this.saveList(this.storyTitle,this.story);
// Add a new record to the top of the history stack
this.history = this.wiki.getTiddlerData(this.historyTitle,[]);
this.history.push({title: draftTitle});
this.wiki.setTiddlerData(this.historyTitle,this.history);
event.stopPropagation();
return false;
};
exports.executeMacro = function() {
// Compute the titles of the story and history list tiddlers
this.storyTitle = this.params.story || "$:/StoryList";
this.historyTitle = this.params.history || "$:/HistoryList";
var attributes = {};
if(this.classes) {
attributes["class"] = this.classes.slice(0);
}
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
return $tw.Tree.Element("div",attributes,this.content,{
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-close","tw-NavigateBack","tw-NewTiddler"],
eventHandler: this
});
};
})();

View File

@ -1,42 +0,0 @@
/*\
title: $:/core/modules/macros/password.js
type: application/javascript
module-type: macro
Allows a password to be set
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "password",
params: {
name: {byName: "default", type: "text"}
}
};
exports.executeMacro = function() {
var password = $tw.browser ? $tw.utils.getPassword(this.params.name) : "";
var attributes = {
type: "password",
value: password
};
if(this.classes) {
attributes["class"] = this.classes.slice(0);
}
return $tw.Tree.Element("input",attributes,[],{
events: ["keyup","input"],
eventHandler: this
});
};
exports.handleEvent = function(event) {
var password = this.child.domNode.value;
return $tw.utils.savePassword(this.params.name,password);
};
})();

View File

@ -1,195 +0,0 @@
/*\
title: $:/core/modules/macros/reveal.js
type: application/javascript
module-type: macro
The reveal macro shows or hides content according to the value of the text in a specified tiddler.
The parameters are:
* ''state'' - text reference where the hide/reveal state is stored
* ''type'' - type of the hide/reveal state:
** //popup// - a popup - the state tiddler should contain the page coordinates of the button that triggered the popup
** //match// - reveals if the state tiddler matches the match text
** //nomatch// - reveals if the state tiddler does not match the match text
* ''position'' - popup position: //left//, //above//, //aboveright//, //right//, //below// or //belowleft//
* ''text'' - match text
* ''qualifyTiddlerTitles'' - if present, causes the title of the state tiddler to be qualified with the current tiddler stack
* ''default'' - default hide/reveal state: `open` if visible, otherwise hidden
* ''class'' - CSS class(es) to be assigned to the revealed element
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "reveal",
params: {
state: {byPos: 0, type: "tiddler"},
type: {byName: true, type: "text"},
text: {byName: true, type: "text"},
position: {byName: true, type: "text"},
qualifyTiddlerTitles: {byName: true, type: "text"},
"default": {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.readState = function() {
// Start with the default value for being open or closed
if(this.hasParameter("default")) {
this.isOpen = this.params["default"] === "open";
}
// Read the information from the state tiddler
if(this.stateTextRef) {
var state = this.wiki.getTextReference(this.stateTextRef,"",this.tiddlerTitle);
switch(this.params.type) {
case "popup":
this.readPopupState(state);
break;
case "match":
this.readMatchState(state);
break;
case "nomatch":
this.readMatchState(state);
this.isOpen = !this.isOpen;
break;
}
}
};
exports.readMatchState = function(state) {
this.isOpen = state === this.params.text;
};
exports.readPopupState = function(state) {
var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
match = popupLocationRegExp.exec(state);
// Check if the state matches the location regexp
if(match) {
// If so, we're open
this.isOpen = true;
// Get the location
this.popup = {
left: parseFloat(match[1]),
top: parseFloat(match[2]),
width: parseFloat(match[3]),
height: parseFloat(match[4])
};
} else {
// If not, we're closed
this.isOpen = false;
}
};
exports.handleEvent = function(event) {
if(event.type === "click" && this.params.type === "popup") {
// Cancel the popup if we get a click on it
if(this.stateTextRef) {
this.wiki.deleteTextReference(this.stateTextRef);
}
event.preventDefault();
return false;
}
return true;
};
exports.executeMacro = function() {
this.stateTextRef = this.params.state;
if(this.hasParameter("qualifyTiddlerTitles")) {
this.stateTextRef = this.stateTextRef + "(" + this.parents.join(",") + "," + this.tiddlerTitle + ")";
}
this.readState();
var attributes = {
"class": ["tw-reveal"],
style: {}
};
if(this.hasParameter("class")) {
attributes["class"].push(this.params["class"]);
}
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
switch(this.params.type) {
case "popup":
attributes.style.position = "absolute";
attributes["class"].push("tw-popup");
break;
}
attributes.style = {display: this.isOpen ? (this.isBlock ? "block" : "inline") : "none"};
var child = $tw.Tree.Element(this.isBlock ? "div" : "span",attributes,this.isOpen ? this.content : [],{
events: ["click"],
eventHandler: this
});
child.execute(this.parents,this.tiddlerTitle);
return child;
};
exports.postRenderInDom = function() {
switch(this.params.type) {
case "popup":
if(this.isOpen) {
this.child.domNode.style.position = "absolute";
this.child.domNode.style.zIndex = "1000";
switch(this.params.position) {
case "left":
this.child.domNode.style.left = (this.popup.left - this.child.domNode.offsetWidth) + "px";
this.child.domNode.style.top = this.popup.top + "px";
break;
case "above":
this.child.domNode.style.left = this.popup.left + "px";
this.child.domNode.style.top = (this.popup.top - this.child.domNode.offsetHeight) + "px";
break;
case "aboveright":
this.child.domNode.style.left = (this.popup.left + this.popup.width) + "px";
this.child.domNode.style.top = (this.popup.top + this.popup.height - this.child.domNode.offsetHeight) + "px";
break;
case "right":
this.child.domNode.style.left = (this.popup.left + this.popup.width) + "px";
this.child.domNode.style.top = this.popup.top + "px";
break;
case "belowleft":
this.child.domNode.style.left = (this.popup.left + this.popup.width - this.child.domNode.offsetWidth) + "px";
this.child.domNode.style.top = (this.popup.top + this.popup.height) + "px";
break;
default: // Below
this.child.domNode.style.left = this.popup.left + "px";
this.child.domNode.style.top = (this.popup.top + this.popup.height) + "px";
break;
}
}
break;
}
};
exports.refreshInDom = function(changes) {
var needChildrenRefresh = true, // Avoid refreshing the children nodes if we don't need to
t;
// Re-read the open state
this.readState();
// Render the children if we're open and we don't have any children yet
if(this.isOpen && this.child.children.length === 0) {
// Install the children and execute them
this.child.children = this.content;
for(t=0; t<this.child.children.length; t++) {
this.child.children[t].execute(this.parents,this.tiddlerTitle);
this.child.children[t].renderInDom(this.child.domNode);
}
needChildrenRefresh = false; // Don't refresh the children if we've just created them
}
// Refresh the children
if(needChildrenRefresh) {
for(t=0; t<this.child.children.length; t++) {
this.child.children[t].refreshInDom(changes);
}
}
// Set the visibility of the children
this.child.domNode.style.display = this.isOpen ? (this.isBlock ? "block" : "inline") : "none";
// Position the content if required
this.postRenderInDom();
};
})();

View File

@ -1,114 +0,0 @@
/*\
title: $:/core/modules/macros/scrollable.js
type: application/javascript
module-type: macro
Creates a scrollable frame around its content
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "scrollable",
params: {
width: {byName: true, type: "text"},
height: {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
var innerClasses = ["tw-scrollable-inner"],
innerAttributes = {
"class": innerClasses,
style: {
overflow: "visible",
position: "relative"
}
},
outerClasses = ["tw-scrollable","tw-scrollable-outer"],
outerAttributes = {
"class": outerClasses,
style: {
overflow: "auto",
"-webkit-overflow-scrolling": "touch",
"white-space": "nowrap"
}
};
if(this.hasParameter("class")) {
outerClasses.push(this.params["class"]);
}
if(this.classes) {
$tw.utils.pushTop(outerClasses,this.classes);
}
if(this.hasParameter("width")) {
outerAttributes.style.width = this.params.width;
}
if(this.hasParameter("height")) {
outerAttributes.style.height = this.params.height;
}
this.innerFrame = $tw.Tree.Element("div",innerAttributes,this.content);
this.outerFrame = $tw.Tree.Element("div",outerAttributes,[this.innerFrame],{
events: ["tw-scroll"],
eventHandler: this
});
this.outerFrame.execute(this.parents,this.tiddlerTitle);
return this.outerFrame;
};
exports.handleEvent = function(event) {
if(event.type === "tw-scroll") {
return this.handleScrollEvent(event);
}
return true;
}
exports.handleScrollEvent = function(event) {
var domNode = event.target,
bounds = {
left: domNode.offsetLeft,
top: domNode.offsetTop,
width: domNode.offsetWidth,
height: domNode.offsetHeight
};
// Walk up the tree adjusting the offset bounds by each offsetParent
while(domNode.offsetParent && domNode.offsetParent !== this.innerFrame.domNode) {
domNode = domNode.offsetParent;
bounds.left += domNode.offsetLeft;
bounds.top += domNode.offsetTop;
}
this.cancelScroll();
this.startTime = new Date();
this.startX = this.child.domNode.scrollLeft;
this.startY = this.child.domNode.scrollTop;
this.endX = bounds.left;
this.endY = bounds.top;
if((this.endX < this.startX) || (this.endX > (this.startX + this.child.domNode.offsetWidth)) || (this.endY < this.startY) || (this.endY > (this.startY + this.child.domNode.offsetHeight))) {
var self = this;
this.scrollTimerId = window.setInterval(function() {
var t = ((new Date()) - self.startTime) / $tw.config.preferences.animationDuration;
if(t >= 1) {
self.cancelScroll();
t = 1;
}
t = $tw.utils.slowInSlowOut(t);
self.child.domNode.scrollLeft = self.startX + (self.endX - self.startX) * t;
self.child.domNode.scrollTop = self.startY + (self.endY - self.startY) * t;
}, 10);
}
event.stopPropagation();
return false;
};
exports.cancelScroll = function() {
if(this.scrollTimerId) {
window.clearInterval(this.scrollTimerId);
this.scrollTimerId = null;
}
};
})();

View File

@ -1,54 +0,0 @@
/*\
title: $:/core/modules/macros/serialize.js
type: application/javascript
module-type: macro
Serialize macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "serialize",
params: {
filter: {byPos: 0, type: "filter"},
as: {byPos: 1, type: "text"},
removePrefix: {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
var as = this.params.as || "text/plain",
t;
if(this.hasParameter("filter")) {
var titles = this.wiki.filterTiddlers(this.params.filter),
tiddlers = [],
result = [];
if(this.hasParameter("removePrefix")) {
for(t=0; t<titles.length; t++) {
var originalTiddler = this.wiki.getTiddler(titles[t]),
title = titles[t];
if(title.indexOf(this.params.removePrefix) === 0) {
title = title.substr(this.params.removePrefix.length);
tiddlers.push(new $tw.Tiddler(originalTiddler,{title: title}));
}
}
} else {
for(t=0; t<titles.length; t++) {
tiddlers.push(this.wiki.getTiddler(titles[t]));
}
}
result.push(this.wiki.serializeTiddlers(tiddlers,as));
return $tw.Tree.Element("pre",{},[
$tw.Tree.Text(result.join("\n"))
]);
}
return null;
};
})();

View File

@ -1,177 +0,0 @@
/*\
title: $:/core/modules/macros/slider.js
type: application/javascript
module-type: macro
!Introduction
The slider macro is used to selectively reveal a chunk of text. By default, it renders as a button that may be clicked or touched to reveal the enclosed text.
The enclosed text can be a string of WikiText or be taken from a target tiddler.
The current state of the slider can be stored as the string "open" or "closed" in a specified tiddler. If the value of that tiddler changes then the slider is automatically updated. If no state tiddler is specified then the state of the slider isn't retained, but the slider still works as expected.
!!Parameters
|`state` //(defaults to 1st parameter)// |The title of the tiddler to contain the current state of the slider |
|`default` |The initial state of the slider, either `open` or `closed` |
|`class` |A CSS class to be applied to the slider root element |
|`content` |The WikiText to be enclosed in the slider. Overrides the `target` parameter, if present |
|`target` //(defaults to 2nd parameter)// |The title of the tiddler that contains the enclosed text. Ignored if the `content` parameter is specified |
|`label` //(defaults to 3rd parameter)// |The plain text to be displayed as the label for the slider button |
|`tooltip` //(defaults to 4th parameter)// |The plain text tooltip to be displayed when the mouse hovers over the slider button |
!!Markup
The markup generated by the slider macro is:
{{{
<span class="tw-slider {user defined class}">
<a class="btn-info">{slider label}</a>
<div class="tw-slider-body" style="display:{state}">{slider content}</div>
</span>
}}}
!!Examples
A minimal slider:
{{{
<<slider target:MyTiddler>>
}}}
!!Notes
The slider is a good study example of a simple interactive macro.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "slider",
params: {
state: {byPos: 0, type: "tiddler"},
target: {byPos: 1, type: "tiddler"},
label: {byPos: 2, type: "text"},
tooltip: {byPos: 3, type: "text"},
"default": {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.getOpenState = function() {
if(this.hasParameter("state")) {
var stateTiddler = this.wiki.getTiddler(this.params.state);
if(stateTiddler) {
return stateTiddler.fields.text.trim() === "open";
}
}
if(this.hasParameter("default")) {
return this.params["default"] === "open";
}
return false;
};
exports.saveOpenState = function() {
if(this.hasParameter("state")) {
var stateTiddler = this.wiki.getTiddler(this.params.state) || {title: this.params.state, text: ""};
this.wiki.addTiddler(new $tw.Tiddler(stateTiddler,{text: this.isOpen ? "open" : "closed"}));
return true;
}
return false;
};
exports.getSliderChildren = function() {
// Use the target tiddler if specified
if(this.hasParameter("target")) {
return [$tw.Tree.Macro("tiddler",{
srcParams: {target: this.params.target},
wiki: this.wiki
})];
} else {
// Otherwise use the content of the macro
return this.content;
}
};
exports.handleEvent = function(event) {
if(event.type === "click") {
if(event.target === this.child.domNode.firstChild) {
this.isOpen = !this.isOpen;
if(!this.saveOpenState()) {
this.refreshInDom({});
}
event.preventDefault();
return false;
} else {
return true;
}
}
return true;
};
exports.executeMacro = function() {
this.isOpen = this.getOpenState();
var sliderChildren = [];
if(this.isOpen) {
sliderChildren = this.getSliderChildren();
}
var attributes = {
"class": ["tw-slider"]
};
if(this.hasParameter("class")) {
attributes["class"].push(this.params["class"]);
}
if(this.classes) {
$tw.utils.pushTop(attributes["class"],this.classes);
}
if(this.hasParameter("state")) {
attributes["data-tw-slider-type"] = this.params.state;
}
if(this.hasParameter("tooltip")) {
attributes.alt = this.params.tooltip;
attributes.title = this.params.tooltip;
}
var child = $tw.Tree.Element("span",
attributes,
[
$tw.Tree.Element("a",
{
"class": ["btn","btn-info"]
},[
$tw.Tree.Text(this.params.label ? this.params.label : this.params.target)
]
),
$tw.Tree.Element("div",
{
"class": ["tw-slider-body"],
"style": {"display": this.isOpen ? "block" : "none"}
},
sliderChildren
)
],{
events: ["click"],
eventHandler: this
}
);
child.execute(this.parents,this.tiddlerTitle);
return child;
};
exports.refreshInDom = function(changes) {
var needChildrenRefresh = true; // Avoid refreshing the children nodes if we don't need to
// If the state tiddler has changed then reset the open state
if(this.hasParameter("state") && $tw.utils.hop(changes,this.params.state)) {
this.isOpen = this.getOpenState();
}
// Render the children if the slider is open and we don't have any children yet
if(this.isOpen && this.child.children[1].children.length === 0) {
// Remove the existing dom node for the body
this.child.domNode.removeChild(this.child.children[1].domNode);
// Get the slider children and execute it
this.child.children[1].children = this.getSliderChildren();
this.child.children[1].execute(this.parents,this.tiddlerTitle);
this.child.children[1].renderInDom(this.child.domNode,null);
needChildrenRefresh = false; // Don't refresh the children if we've just created them
}
// Set the visibility of the slider children
this.child.children[1].domNode.style.display = this.isOpen ? "block" : "none";
// Refresh any children
if(needChildrenRefresh) {
this.child.refreshInDom(changes);
}
};
})();

View File

@ -1,160 +0,0 @@
/*\
title: $:/core/modules/macros/tiddler.js
type: application/javascript
module-type: macro
The tiddler macros transcludes another macro into the tiddler being rendered.
Parameters:
target: the title of the tiddler to transclude
template: the title of the tiddler to use as a template for the transcluded tiddler
with: optional parameters to be substituted into the rendered tiddler
The simplest case is to just supply a target tiddler:
{{{
<<tiddler Foo>> or <<transclude target:Foo>>
}}}
This will render the tiddler Foo within the current tiddler. If the tiddler Foo includes
the view macro (or other macros that reference the fields of the current tiddler), then the
fields of the tiddler Foo will be accessed.
If you want to transclude the tiddler as a template, so that the fields referenced by the view
macro are those of the tiddler doing the transcluding, then you can instead specify the tiddler
as a template:
{{{
<<tiddler template:Foo>>
}}}
The effect is the same as the previous example: the text of the tiddler Foo is rendered. The
difference is that the view macro will access the fields of the tiddler doing the transcluding.
The `target` and `template` parameters may be combined:
{{{
<<tiddler target:Foo template:Bar>>
}}}
Here, the text of the tiddler `Bar` will be transcluded, with the macros within it accessing the fields
of the tiddler `Foo`.
Finally, the `with` parameter is used to substitute values for the special markers $1, $2, $3 etc. The
substitutions are performed on the tiddler whose text is being rendered: either the tiddler named in
the `template` parameter or, if that parameter is missing, the tiddler named in the `target` parameter.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "tiddler",
cascadeParams: true, // Cascade names of named parameters to following anonymous parameters
params: {
target: {byName: "default", type: "tiddler"},
targetVia: {byName: true, type: "tiddler"},
template: {byName: true, type: "tiddler"},
"with": {byName: true, type: "text", dependentAll: true}
}
};
exports.evaluateDependencies = function() {
var dependencies = new $tw.Dependencies(),
template = this.srcParams.template;
if(template === undefined) {
template = this.srcParams.target;
}
if(typeof template === "function") {
dependencies.dependentAll = true;
} else {
dependencies.addDependency(template,true);
}
var targetVia = this.srcParams.targetVia;
if(typeof targetVia === "function") {
dependencies.dependentAll = true;
} else {
dependencies.addDependency(targetVia,true);
}
return dependencies;
};
exports.executeMacro = function() {
var renderTitle, renderTemplateTitle, renderTemplateTree,
children, parseTree,
t,
parents = this.parents.slice(0),
parseOptions = {};
// If there's no render title specified then use the current tiddler title
if(this.hasParameter("target")) {
renderTitle = this.params.target;
} else if(this.hasParameter("targetVia")) {
renderTitle = this.wiki.getTextReference(this.params.targetVia,null,this.tiddlerTitle);
} else {
renderTitle = this.tiddlerTitle;
}
// Get the render tree for the template
if(this.content.length > 0) {
renderTemplateTree = this.content;
} else {
if(this.hasParameter("template")) {
renderTemplateTitle = this.params.template;
} else {
renderTemplateTitle = renderTitle;
}
// Check for recursion
if(parents.indexOf(this.params.templateTitle) !== -1) {
renderTemplateTree = $tw.Tree.errorNode("Tiddler recursion error in <<tiddler>> macro");
} else {
parents.push(renderTemplateTitle);
renderTemplateTree = [];
// Check for substitution parameters
if(this.hasParameter("with")) {
parseOptions["with"] = [undefined,this.params["with"]]; // TODO: Allow for more than one with: parameter
}
parseTree = this.wiki.parseTiddler(renderTemplateTitle,parseOptions);
children = parseTree ? parseTree.tree : [];
for(t=0; t<children.length; t++) {
renderTemplateTree.push(children[t].clone());
}
}
}
// Execute macros within the children
for(t=0; t<renderTemplateTree.length; t++) {
renderTemplateTree[t].execute(parents,renderTitle);
}
// Set up the attributes for the wrapper element
var attributes = {
"class": []
};
if(!this.wiki.tiddlerExists(renderTitle)) {
attributes["class"].push("tw-tiddler-missing");
}
// Return the children
return $tw.Tree.Element(this.isBlock ? "div" : "span",attributes,renderTemplateTree);
};
exports.refreshInDom = function(changes) {
var renderTitle;
// Set the class for missing tiddlers
if(this.hasParameter("target")) {
renderTitle = this.params.target;
} else {
renderTitle = this.tiddlerTitle;
}
if(renderTitle) {
$tw.utils.toggleClass(this.child.domNode,"tw-tiddler-missing",!this.wiki.tiddlerExists(renderTitle));
}
// Rerender the tiddler if it is impacted by the changes
if(this.dependencies.hasChanged(changes,this.renderTitle)) {
// Manually reexecute and rerender this macro
this.reexecuteInDom();
} else {
this.child.refreshInDom(changes);
}
};
})();

View File

@ -1,25 +0,0 @@
/*\
title: $:/core/modules/macros/version.js
type: application/javascript
module-type: macro
Version macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "version",
params: {
}
};
exports.executeMacro = function() {
return $tw.Tree.Text($tw.version);
};
})();

View File

@ -1,58 +0,0 @@
/*\
title: $:/core/modules/macros/video.js
type: application/javascript
module-type: macro
Video macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "video",
params: {
src: {byName: "default", type: "text"},
type: {byName: true, type: "text"},
width: {byName: true, type: "text"},
height: {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
var src = this.params.src,
videoType = this.params.type || "vimeo",
videoWidth = this.params.width || 640,
videoHeight = this.params.height || 360;
switch(videoType) {
case "vimeo":
return $tw.Tree.Element("iframe",{
src: "http://player.vimeo.com/video/" + src + "?autoplay=0",
width: videoWidth,
height: videoHeight,
frameborder: 0
});
case "youtube":
return $tw.Tree.Element("iframe",{
type: "text/html",
src: "http://www.youtube.com/embed/" + src,
width: videoWidth,
height: videoHeight,
frameborder: 0
});
case "archiveorg":
return $tw.Tree.Element("iframe",{
src: "http://www.archive.org/embed/" + src,
width: videoWidth,
height: videoHeight,
frameborder: 0
});
default:
return null;
}
};
})();

View File

@ -1,73 +0,0 @@
/*\
title: $:/core/modules/macros/view.js
type: application/javascript
module-type: macro
View macro
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "view",
dependentOnContextTiddler: true,
params: {
field: {byPos: 0, type: "text"},
format: {byPos: 1, type: "text"},
template: {byPos: 2, type: "text"}
}
};
exports.executeMacro = function() {
var tiddler = this.wiki.getTiddler(this.tiddlerTitle),
field = this.hasParameter("field") ? this.params.field : "title",
value;
// Get the value to display
if(tiddler) {
if(field === "text") {
value = this.wiki.getTiddlerText(this.tiddlerTitle);
} else {
value = tiddler.fields[field];
}
} else { // Use a special value if the tiddler is missing
switch(field) {
case "text":
value = "";
break;
case "title":
value = this.tiddlerTitle;
break;
case "modified":
case "created":
value = new Date();
break;
default:
value = "Missing tiddler '" + this.tiddlerTitle + "'";
break;
}
}
// Figure out which viewer to use
// TODO: Tiddler field modules should be able to specify a field type from which the viewer is derived
var Viewer;
if(this.params.format) {
Viewer = this.wiki.macros.view.fieldviewers[this.params.format];
}
if(!Viewer) {
Viewer = this.wiki.macros.view.fieldviewers.text;
}
this.viewer = new Viewer(this,tiddler,field,value);
// Call the viewer to generate the content
return this.viewer.render();
};
exports.postRenderInDom = function() {
if(this.viewer.postRenderInDom) {
this.viewer.postRenderInDom();
}
};
})();

View File

@ -1,33 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/date.js
type: application/javascript
module-type: fieldviewer
A viewer for viewing tiddler fields as a date
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var DateViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
DateViewer.prototype.render = function() {
var template = this.viewMacro.params.template || "DD MMM YYYY";
if(this.value === undefined) {
return $tw.Tree.Text("");
} else {
return $tw.Tree.Text($tw.utils.formatDateString(this.value,template));
}
};
exports.date = DateViewer;
})();

View File

@ -1,39 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/link.js
type: application/javascript
module-type: fieldviewer
A viewer for viewing tiddler fields as a link
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var LinkViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
LinkViewer.prototype.render = function() {
if(this.value === undefined) {
return $tw.Tree.Text("");
} else {
var link = $tw.Tree.Macro("link",{
srcParams: {to: this.value},
content: [$tw.Tree.Text(this.value)],
isBlock: this.viewMacro.isBlock,
wiki: this.viewMacro.wiki
});
link.execute(this.viewMacro.parents,this.viewMacro.tiddlerTitle);
return link;
}
};
exports.link = LinkViewer;
})();

View File

@ -1,75 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/relativedate.js
type: application/javascript
module-type: fieldviewer
A viewer for viewing tiddler fields as a relative date
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var RelativeDateViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
RelativeDateViewer.prototype.render = function() {
if(!this.tiddler ||this.value === undefined) {
return $tw.Tree.Text("");
} else {
this.relativeDate = $tw.utils.getRelativeDate((new Date()) - this.value);
return $tw.Tree.Element(this.viewMacro.isBlock ? "div" : "span",{},[
$tw.Tree.Text(
this.relativeDate.description
)
]);
}
};
/*
Trigger the timer when the relative date is put into the DOM
*/
RelativeDateViewer.prototype.postRenderInDom = function() {
if(this.relativeDate) {
this.update();
}
};
/*
Trigger the timer for the next update of the relative date
*/
RelativeDateViewer.prototype.setTimer = function() {
var self = this;
if(this.relativeDate.updatePeriod < 24 * 60 * 60 * 1000) {
window.setTimeout(function() {
// Only call the update function if the dom node is still in the document
if($tw.utils.domContains(document,self.viewMacro.child.domNode)) {
self.update.call(self);
}
},this.relativeDate.updatePeriod);
}
};
/*
Update the relative date display, and trigger the timer for the next update
*/
RelativeDateViewer.prototype.update = function() {
this.relativeDate = $tw.utils.getRelativeDate((new Date()) - this.value);
if(this.relativeDate.delta > 0) {
while(this.viewMacro.child.domNode.hasChildNodes()) {
this.viewMacro.child.domNode.removeChild(this.viewMacro.child.domNode.firstChild);
}
this.viewMacro.child.domNode.appendChild(document.createTextNode(this.relativeDate.description));
this.setTimer();
}
};
exports.relativedate = RelativeDateViewer;
})();

View File

@ -1,37 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/text.js
type: application/javascript
module-type: fieldviewer
A viewer for viewing tiddler fields as plain text
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var TextViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
TextViewer.prototype.render = function() {
// Get the value as a string
if(this.field !== "text" && this.tiddler) {
this.value = this.tiddler.getFieldString(this.field);
}
// Return the text
if(this.value === undefined || this.value === null) {
return $tw.Tree.Text("");
} else {
return $tw.Tree.Text(this.value);
}
};
exports.text = TextViewer;
})();

View File

@ -1,38 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/transclude.js
type: application/javascript
module-type: fieldviewer
A viewer that transcludes the tiddler whose title is specified in the viewed field
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var TranscludeViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
TranscludeViewer.prototype.render = function() {
if(this.tiddler && this.viewMacro.params.field && (this.viewMacro.params.field in this.tiddler.fields)) {
var children = this.viewMacro.wiki.parseTiddler(this.tiddler.fields[this.viewMacro.params.field]).tree,
childrenClone = [],t;
for(t=0; t<children.length; t++) {
childrenClone.push(children[t].clone());
}
for(t=0; t<childrenClone.length; t++) {
childrenClone[t].execute(this.viewMacro.parents,this.viewMacro.tiddlerTitle);
}
return $tw.Tree.Element(this.viewMacro.isBlock ? "div" : "span",{},childrenClone);
}
};
exports.transclude = TranscludeViewer;
})();

View File

@ -1,49 +0,0 @@
/*\
title: $:/core/modules/macros/view/viewers/wikified.js
type: application/javascript
module-type: fieldviewer
A viewer for viewing tiddler fields as wikified text
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var WikifiedViewer = function(viewMacro,tiddler,field,value) {
this.viewMacro = viewMacro;
this.tiddler = tiddler;
this.field = field;
this.value = value;
};
WikifiedViewer.prototype.render = function() {
// Check for recursion
var parents = this.viewMacro.parents,
children,t,childrenClone = [];
if(this.tiddler && this.viewMacro.params.field === "text") {
if(parents.indexOf(this.tiddler.fields.title) !== -1) {
children = [$tw.Tree.errorNode("Tiddler recursion error in <<view>> macro")];
} else {
children = this.viewMacro.wiki.parseTiddler(this.tiddler.fields.title).tree;
}
parents = parents.slice(0);
parents.push(this.tiddler.fields.title);
} else {
children = this.viewMacro.wiki.parseText("text/vnd.tiddlywiki",this.value).tree;
}
// Clone and execute the parsed wikitext
for(t=0; t<children.length; t++) {
childrenClone.push(children[t].clone());
}
for(t=0; t<childrenClone.length; t++) {
childrenClone[t].execute(parents,this.viewMacro.tiddlerTitle);
}
return $tw.Tree.Element(this.viewMacro.isBlock ? "div" : "span",{},childrenClone);
};
exports.wikified = WikifiedViewer;
})();

View File

@ -1,156 +0,0 @@
/*\
title: $:/core/modules/macros/zoomable.js
type: application/javascript
module-type: macro
Creates a zoomable frame around its content
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "zoomable",
params: {
width: {byName: true, type: "text"},
height: {byName: true, type: "text"},
"class": {byName: true, type: "text"}
}
};
exports.executeMacro = function() {
var innerClasses = ["tw-zoomable-inner"],
innerAttributes = {
"class": innerClasses,
style: {
overflow: "visible",
position: "relative"
}
},
outerClasses = ["tw-zoomable","tw-zoomable-outer"],
outerAttributes = {
"class": outerClasses,
style: {
overflow: "hidden",
"white-space": "nowrap"
}
};
if(this.hasParameter("class")) {
outerClasses.push(this.params["class"]);
}
if(this.classes) {
$tw.utils.pushTop(outerClasses,this.classes);
}
if(this.hasParameter("width")) {
outerAttributes.style.width = this.params.width;
}
if(this.hasParameter("height")) {
outerAttributes.style.height = this.params.height;
}
var self = this;
this.innerFrame = $tw.Tree.Element("div",innerAttributes,this.content);
this.outerFrame = $tw.Tree.Element("div",outerAttributes,[this.innerFrame],{
events: ["tw-scroll","click"],
eventHandler: this
});
this.outerFrame.execute(this.parents,this.tiddlerTitle);
this.translateX = 0;
this.translateY = 0;
this.scale = 1;
return this.outerFrame;
};
exports.postRenderInDom = function() {
this.zoomAll();
};
/*
Bring a dom node into view by setting the viewport (translation and scale factors) appropriately.
The calculations are a little hairy. The problem is that we want to deal with coordinates that take into account CSS transformations applied to elements. The most reliable way to do that is to use getBoundingClientRect, which returns the bounding rectangle in screen coordinates of an element, taking into account any transformations.
So, we measure the position of the target element and then adjust it to compensate for the current viewport settings.
*/
exports.setViewPort = function(domNode) {
var zoomPosString = domNode.getAttribute("data-tw-zoom");
if(zoomPosString) {
var zoomPos = JSON.parse(zoomPosString);
if(zoomPos) {
// Compute the transform for the inner frame
this.translateX = -zoomPos.x;
this.translateY = -zoomPos.y;
this.scale = this.outerFrame.domNode.offsetWidth / zoomPos.w;
$tw.utils.setStyle(this.innerFrame.domNode,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transformOrigin: "0% 0%"},
{transform: "translate(" + this.translateX * this.scale + "px," + this.translateY * this.scale + "px) scale(" + this.scale + ")"}
]);
}
}
};
exports.zoomAll = function() {
var bounds = {left: 0, top: 0, right: 0, bottom: 0},
scanChildren = function(nodes) {
for(var c=0; c<nodes.length; c++) {
var node = nodes[c];
if(node.getAttribute && node.getAttribute("data-tw-zoom")) {
var zoom = JSON.parse(node.getAttribute("data-tw-zoom"));
if(zoom === true) {
zoom = {
x: node.offsetLeft,
y: node.offsetTop,
w: node.scrollWidth,
h: node.scrollHeight
};
}
if(zoom.x < bounds.left) {
bounds.left = zoom.x;
}
if(zoom.y < bounds.top) {
bounds.top = zoom.y;
}
if((zoom.x + zoom.w) > bounds.right) {
bounds.right = zoom.x + zoom.w;
}
if((zoom.y + zoom.h) > bounds.bottom) {
bounds.bottom = zoom.y + zoom.h;
}
}
if(node.hasChildNodes()) {
scanChildren(node.childNodes);
}
}
};
scanChildren(this.innerFrame.domNode.childNodes);
this.translateX = bounds.left;
this.translateY = bounds.top;
this.scale = this.outerFrame.domNode.offsetWidth / (bounds.right - bounds.left);
$tw.utils.setStyle(this.innerFrame.domNode,[
{transition: $tw.utils.roundTripPropertyName("transform") + " " + $tw.config.preferences.animationDurationMs + " ease-in-out"},
{transformOrigin: "0% 0%"},
{transform: "translate(" + this.translateX * this.scale + "px," + this.translateY * this.scale + "px) scale(" + this.scale + ")"}
]);
};
exports.handleEvent = function(event) {
if(event.type === "tw-scroll") {
return this.handleScrollEvent(event);
}
if(event.type === "click") {
this.zoomAll();
return false;
}
return true;
}
exports.handleScrollEvent = function(event) {
this.setViewPort(event.target);
event.stopPropagation();
return false;
};
})();

View File

@ -1,40 +0,0 @@
/*\
title: $:/core/modules/parsers/old/imageparser.js
type: application/javascript
module-type: parser
Parses an image into a parse tree containing an HTML img element
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var ImageParser = function(options) {
this.wiki = options.wiki;
};
ImageParser.prototype.parse = function(type,text) {
var element = "img",
src;
if(type === "application/pdf" || type === ".pdf") {
src = "data:application/pdf;base64," + text;
element = "embed";
} else if(type === "image/svg+xml" || type === ".svg") {
src = "data:image/svg+xml," + encodeURIComponent(text);
} else {
src = "data:" + type + ";base64," + text;
}
return new $tw.Renderer([$tw.Tree.Element(element,{src: src})],new $tw.Dependencies());
};
exports["image/svg+xml"] = ImageParser;
exports["image/jpg"] = ImageParser;
exports["image/jpeg"] = ImageParser;
exports["image/png"] = ImageParser;
exports["image/gif"] = ImageParser;
exports["application/pdf"] = ImageParser;
})();

View File

@ -1,12 +0,0 @@
{
"tiddlers": [
{
"file": "../../../../../../node_modules/esprima/esprima.js",
"fields": {
"title": "$:/core/modules/parsers/javascriptparser/esprima/esprima.js",
"type": "application/javascript",
"module-type": "library"
}
}
]
}

View File

@ -1,110 +0,0 @@
/*\
title: $:/core/modules/parsers/javascriptparser/javascriptparser.js
type: application/javascript
module-type: parser
Parses a JavaScript program into a parse tree
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var esprima = require("./esprima/esprima.js");
// Initialise the parser
var JavaScriptParser = function(options) {
this.wiki = options.wiki;
};
// Parse a string of JavaScript code and return the parse tree as a wikitext parse tree
JavaScriptParser.prototype.parse = function(type,code) {
// Try to parse the code
if(!code) {
return new $tw.Renderer([
$tw.Tree.Element("pre",{"class": "javascript-source"},[
$tw.Tree.Text("")
])
],new $tw.Dependencies(),this.wiki);
}
var parseTree;
try {
parseTree = esprima.parse(code,{comment: true,tokens: true,range: true});
} catch(ex) {
// Return a helpful error if the parse failed
return new $tw.Renderer([
$tw.Tree.Element("pre",{"class": "javascript-source"},[
$tw.Tree.Text(code.substring(0,ex.index)),
$tw.Tree.errorNode(ex),
$tw.Tree.Text(code.substring(ex.index))
])
],new $tw.Dependencies(),this.wiki);
}
// Helpers to render the comments and tokens with the appropriate classes
var self = this,
result = [],
nextComment = 0,
nextToken = 0,
currPos = 0;
var renderWhitespace = function(nextPos) {
if(currPos < nextPos) {
result.push($tw.Tree.Text(code.substring(currPos,nextPos)));
}
},
renderComment = function(comment) {
var text = comment.value,
element,
classes = ["javascript-comment"],
content = [];
renderWhitespace(comment.range[0]);
if(comment.type === "Block") {
element = "div";
classes.push("javascript-block-comment");
content.push($tw.Tree.Text("/*"));
content.push.apply(content,self.wiki.parseText("text/vnd.tiddlywiki",text).tree);
content.push($tw.Tree.Text("*/"));
} else {
element = "span";
classes.push("javascript-line-comment");
content.push($tw.Tree.Text("//"));
content.push.apply(content,self.wiki.parseText("text/vnd.tiddlywiki-run",text).tree);
content.push($tw.Tree.Text("\n"));
}
result.push($tw.Tree.Element(element,{"class": classes},content));
currPos = comment.range[1] + 1;
},
renderToken = function(token) {
renderWhitespace(token.range[0]);
result.push($tw.Tree.Element("span",{
"class": "javascript-" + token.type.toLowerCase()
},[
$tw.Tree.Text(token.value)
]));
currPos = token.range[1] + 1;
};
// Process the tokens interleaved with the comments
while(nextComment < parseTree.comments.length || nextToken < parseTree.tokens.length) {
if(nextComment < parseTree.comments.length && nextToken < parseTree.tokens.length) {
if(parseTree.comments[nextComment].range[0] < parseTree.tokens[nextToken].range[0]) {
renderComment(parseTree.comments[nextComment++]);
} else {
renderToken(parseTree.tokens[nextToken++]);
}
} else if(nextComment < parseTree.comments.length) {
renderComment(parseTree.comments[nextComment++]);
} else {
renderToken(parseTree.tokens[nextToken++]);
}
}
renderWhitespace(code.length);
// Wrap the whole lot in a `<PRE>`
return new $tw.Renderer([
$tw.Tree.Element("pre",{"class": "javascript-source"},result)
],new $tw.Dependencies(),this.wiki);
};
exports["application/javascript"] = JavaScriptParser;
})();

View File

@ -1,50 +0,0 @@
/*\
title: $:/core/modules/parsers/jsonparser.js
type: application/javascript
module-type: parser
Parses a JSON object into a parse tree
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var renderObject = function(obj) {
var children = [],t;
if($tw.utils.isArray(obj)) {
for(t=0; t<obj.length; t++) {
children.push($tw.Tree.Element("li",{
"class": ["jsonArrayMember"]
},[renderObject(obj[t])]));
}
return $tw.Tree.Element("ul",{
"class": ["jsonArray"]
},children);
} else if(typeof obj === "object") {
for(t in obj) {
children.push($tw.Tree.Element("li",{
"class": ["jsonObjectMember"]
},[$tw.Tree.splitLabelNode("JSON",[$tw.Tree.Text(t)],[renderObject(obj[t])])]));
}
return $tw.Tree.Element("ul",{
"class": ["jsonObject"]
},children);
} else {
return $tw.Tree.labelNode("JSON" + (typeof obj),[$tw.Tree.Text(JSON.stringify(obj))],["jsonValue"]);
}
};
var JSONParser = function(options) {
this.wiki = options.wiki;
};
JSONParser.prototype.parse = function(type,text) {
return new $tw.Renderer([renderObject(JSON.parse(text))],new $tw.Dependencies());
};
exports["application/json"] = JSONParser;
})();

View File

@ -1,26 +0,0 @@
/*\
title: $:/core/modules/parsers/plaintextparser.js
type: application/javascript
module-type: parser
Parses plain text tiddlers
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var PlainTextParser = function(options) {
this.wiki = options.wiki;
};
PlainTextParser.prototype.parse = function(type,text) {
return new $tw.Renderer([$tw.Tree.Element("pre",{},[$tw.Tree.Text(text)])],new $tw.Dependencies());
};
exports["text/plain"] = PlainTextParser;
exports["text/html"] = PlainTextParser;
})();

View File

@ -1,64 +0,0 @@
/*\
title: $:/core/modules/parsers/tiddlytextparser.js
type: application/javascript
module-type: parser
Parses a plain text block that can also contain macros and transclusions.
The syntax for transclusions is:
[[tiddlerTitle]]
The syntax for macros is:
<<macroName params>>
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var TiddlyTextParser = function(options) {
this.wiki = options.wiki;
};
TiddlyTextParser.prototype.parse = function(type,text) {
var output = [],
dependencies = new $tw.Dependencies(),
macroRegExp = /(?:\[\[([^\]]+)\]\])|(?:<<(?:([!@£\$%\^\&\*\(\)`\~'"\|\\\/;\:\.\,\+\=\-\_\{\}])|([^>\s]+))(?:\s*)((?:[^>]|(?:>(?!>)))*)>>((?:\r?\n)?))/mg,
lastMatchPos = 0,
match,
macroNode;
do {
match = macroRegExp.exec(text);
if(match) {
output.push($tw.Tree.Text(text.substring(lastMatchPos,match.index)));
var macroName = match[2] || match[3];
if(match[1]) { // Transclusion
macroNode = $tw.Tree.Macro("tiddler",{
srcParams: {target: match[1]},
wiki: this.wiki
});
} else if(macroName) { // Macro call
macroNode = $tw.Tree.Macro(macroName,{
srcParams: match[4],
wiki: this.wiki,
isBlock: !!match[5]
});
}
output.push(macroNode);
dependencies.mergeDependencies(macroNode.dependencies);
lastMatchPos = match.index + match[0].length;
} else {
output.push($tw.Tree.Text(text.substr(lastMatchPos)));
}
} while(match);
return new $tw.Renderer(output,dependencies);
};
exports["text/vnd.tiddlywiki-css"] = TiddlyTextParser;
exports["text/vnd.tiddlywiki-html"] = TiddlyTextParser;
})();

View File

@ -1,50 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/classblock.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for assigning classes to paragraphs and other blocks. For example:
{{{
{{myClass{
This paragraph will have the CSS class `myClass`.
* The `<ul>` around this list will also have the class `myClass`
* List item 2
}}}
}}}
Note that the opening and closing braces both must be immediately followed by a newline.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "class";
exports.blockParser = true;
exports.regExpString = "\\{\\{(?:[^\\{\\r\\n]+)\\{$\\r?\\n";
exports.parse = function(match,isBlock) {
var tree = [],
reStart = /\{\{([^\{\r\n]+)\{\r?\n/mg,
reEndString = "(\\}\\}\\}$(?:\\r?\\n)?)",
endMatch;
reStart.lastIndex = this.pos;
match = reStart.exec(this.source);
if(match) {
this.pos = match.index + match[0].length;
tree = this.parseBlocks(reEndString);
for(var t=0; t<tree.length; t++) {
tree[t].addClass(match[1]);
}
}
return tree;
};
})();

View File

@ -1,41 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/classrun.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for assigning classes to paragraphs and other blocks. For example:
{{{
{{myClass{This text will have the CSS class `myClass`.
* This will not be recognised as a list
List item 2}}}
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "class";
exports.runParser = true;
exports.regExpString = "\\{\\{(?:[^\\{\\r\\n]+)\\{";
exports.parse = function(match,isBlock) {
var tree,
reStart = /\{\{([^\{\r\n]+)\{/mg,
reEnd = /(\}\}\})/g;
reStart.lastIndex = this.pos;
match = reStart.exec(this.source);
this.pos = match.index + match[0].length;
tree = this.parseRun(reEnd,{leaveTerminator: false});
return [$tw.Tree.Element("span",{"class":match[0]},tree)];
};
})();

View File

@ -1,45 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/codeblock.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for code blocks. For example:
{{{
{{{
This text will not be //wikified//
}}}
}}}
Note that the opening curly braces and the closing curly braces must each be on a line of their own, and not be preceded or followed by white space.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "codeblock";
exports.blockParser = true;
exports.regExpString = "\\{\\{\\{\\r?\\n";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
var regExp = /(\r?\n\}\}\}$)/mg,
text;
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match) {
text = this.source.substring(this.pos,match.index);
this.pos = match.index + match[0].length;
} else {
text = this.source.substr(this.pos);
this.pos = this.sourceLength;
}
return [$tw.Tree.Element("pre",{},[$tw.Tree.Text(text)])];
};
})();

View File

@ -1,46 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/coderun.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for code runs. For example:
{{{
This is a {{{code run}}} and `so is this`.
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "coderun";
exports.runParser = true;
exports.regExpString = "(?:\\{\\{\\{)|(?:`)";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
var regExp,
text;
if(match[0] === "{{{") {
regExp = /(\}\}\})/mg;
} else {
regExp = /(`)/mg;
}
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match) {
text = this.source.substring(this.pos,match.index);
this.pos = match.index + match[0].length;
} else {
text = this.source.substr(this.pos);
this.pos = this.sourceLength;
}
return [$tw.Tree.Element("code",{},[$tw.Tree.Text(text)])];
};
})();

View File

@ -1,33 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/comment.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for HTML comments. For example:
{{{
<!-- This is a comment -->
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "comment";
exports.blockParser = true;
exports.runParser = true;
// Regexp by Stephen Ostermiller, http://ostermiller.org/findhtmlcomment.html
exports.regExpString = "\\<![ \\r\\n\\t]*(?:--(?:[^\\-]|[\\r\\n]|-[^\\-])*--[ \\r\\n\\t]*)\\>";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
return this.parseBlock();
};
})();

View File

@ -1,35 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/dash.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for HTML entities. For example:
{{{
This is an en-dash: --
This is an em-dash: ---
}}}
Dashes must be followed by whitespace in order to be distinguished from strikethrough notation (`--strikethrough--`).
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "dash";
exports.runParser = true;
exports.regExpString = "-{2,3}(?=\\s)";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
var dash = match[0].length === 2 ? "&ndash;" : "&mdash;";
return [$tw.Tree.Entity(dash)];
};
})();

View File

@ -1,78 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/emphasis.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for emphasis. For example:
{{{
This is ''bold'' text
This is //italic// text
This is __underlined__ text
This is ^^superscript^^ text
This is ~~subscript~~ text
This is --strikethrough-- text
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "emphasis";
exports.runParser = true;
exports.regExpString = "''|\/\/|__|\\^\\^|~~|--(?!\\s|$)";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
var el,regExp;
switch(match[0]) {
case "''": // Bold
el = "strong";
regExp = /('')|(\r?\n)/mg;
break;
case "//": // Italics
el = "em";
regExp = /(\/\/)|(\r?\n)/mg;
break;
case "__": // Underline
el = "u";
regExp = /(__)|(\r?\n)/mg;
break;
case "^^":
el = "sup";
regExp = /(\^\^)|(\r?\n)/mg;
break;
case "~~":
el = "sub";
regExp = /(~~)|(\r?\n)/mg;
break;
case "--":
el = "strike";
regExp = /(--)|(\r?\n)/mg;
break;
}
// Parse the run up to the terminator
var tree = this.parseRun(regExp,{leaveTerminator: true});
// Check for the terminator
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match && match.index === this.pos) {
// Only consume the terminator if it isn't a line break
if(match[1]) {
this.pos = match.index + match[0].length;
}
}
return [$tw.Tree.Element(el,{},tree)];
};
})();

View File

@ -1,30 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/entity.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for HTML entities. For example:
{{{
This is a copyright symbol: &copy;
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "entity";
exports.runParser = true;
exports.regExpString = "&#?[a-zA-Z0-9]{2,8};";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
return [$tw.Tree.Entity(match[0])];
};
})();

View File

@ -1,46 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/extlink.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for external links. For example:
{{{
An external link: http://www.tiddlywiki.com/
A suppressed external link: ~http://www.tiddlyspace.com/
}}}
External links can be suppressed by preceding them with `~`.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "extlink";
exports.runParser = true;
var unWikiLink = "~";
exports.regExpString = unWikiLink + "?(?:file|http|https|mailto|ftp|irc|news|data):[^\\s'\"]+(?:/|\\b)";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
if(match[0].substr(0,1) === unWikiLink) {
return [$tw.Tree.Text(match[0].substr(1))];
} else {
var macroNode = $tw.Tree.Macro("link",{
srcParams: {to: match[0]},
content: [$tw.Tree.Text(match[0])],
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode];
}
};
})();

View File

@ -1,45 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/heading.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for headings. For example:
{{{
! Level one heading
A paragraph in level 1.
!! Level two heading
A paragraph in level 2.
}}}
The bang `!` must be the first thing on the line. Any white space before the text of the heading is ignored.
A CSS can be applied to the heading as follows:
{{{
!{{myClass}} This heading will have the class `myClass`
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "heading";
exports.blockParser = true;
exports.regExpString = "!{1,6}";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
var classedRun = this.parseClassedRun(/(\r?\n)/mg);
return [$tw.Tree.Element("h" + match[0].length,{"class": classedRun["class"]},classedRun.tree)];
};
})();

View File

@ -1,82 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/html.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for block and run level HTML elements. For example:
{{{
<aside>
This is an HTML5 aside element
</aside>
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "html";
exports.blockParser = true;
exports.runParser = true;
exports.regExpString = "<[A-Za-z]+\\s*[^>]*>";
exports.parse = function(match,isBlock) {
var reStart = /<([A-Za-z]+)(\s*[^>]*)>/mg,
reLineBreak = /(\r?\n)/mg,
reAttr = /\s*([A-Za-z\-_]+)(?:\s*=\s*(?:("[^"]*")|('[^']*')|([^"'\s]+)))?/mg;
// Process the start regexp to get the attribute portion
reStart.lastIndex = this.pos;
var startMatch = reStart.exec(this.source);
if(startMatch && startMatch.index === this.pos) {
// Process the attributes
var attrMatch = reAttr.exec(startMatch[2]),
attributes = {};
while(attrMatch) {
var name = attrMatch[1],
value;
if(attrMatch[2]) { // Double quoted
value = attrMatch[2].substring(1,attrMatch[2].length-1);
} else if(attrMatch[3]) { // Single quoted
value = attrMatch[3].substring(1,attrMatch[3].length-1);
} else if(attrMatch[4]) { // Unquoted
value = attrMatch[4];
} else { // Valueless
value = true; // TODO: We should have a way of indicating we want an attribute without a value
}
attributes[name] = value;
attrMatch = reAttr.exec(startMatch[2]);
}
this.pos = startMatch.index + startMatch[0].length;
// Check for a line break immediate after the opening tag
reLineBreak.lastIndex = this.pos;
var lineBreakMatch = reLineBreak.exec(this.source);
if(lineBreakMatch && lineBreakMatch.index === this.pos) {
this.pos = lineBreakMatch.index + lineBreakMatch[0].length;
isBlock = true;
} else {
isBlock = false;
}
var reEndString = "(</" + startMatch[1] + ">)",
reEnd = new RegExp(reEndString,"mg"),
content;
if(isBlock) {
content = this.parseBlocks(reEndString);
} else {
content = this.parseRun(reEnd);
}
var element = $tw.Tree.Element(startMatch[1],attributes,content);
reEnd.lastIndex = this.pos;
match = reEnd.exec(this.source);
if(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
}
return [element];
}
};
})();

View File

@ -1,63 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/image.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for images. For example:
{{{
[img[MyPicture]]
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "image";
exports.runParser = true;
exports.regExpString = "\\[(?:[<>]?)[Ii][Mm][Gg]\\[(?:(?:[^\\|\\]]+)\\|)?(?:[^\\[\\]\\|]+)\\](?:\\[(?:[^\\]]*)\\])?\\]";
exports.parse = function(match,isBlock) {
var regExp = /\[([<>]?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
var srcParams = {};
if(match[1] === "<") {
srcParams.alignment = "left";
} else if(match[1] === ">") {
srcParams.alignment = "right";
}
if(match[2]) {
srcParams.text = match[2];
}
if(match[3]) {
srcParams.src = match[3];
}
var imageMacroNode = $tw.Tree.Macro("image",{
srcParams: srcParams,
wiki: this.wiki
});
this.dependencies.mergeDependencies(imageMacroNode.dependencies);
if(match[4]) {
var linkMacroNode = $tw.Tree.Macro("link",{
srcParams: {to: match[4]},
content: [imageMacroNode],
wiki: this.wiki
});
this.dependencies.mergeDependencies(linkMacroNode.dependencies);
return [linkMacroNode];
} else {
return [imageMacroNode];
}
}
return [];
};
})();

View File

@ -1,121 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/list.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for lists. For example:
{{{
* This is an unordered list
* It has two items
# This is a numbered list
## With a subitem
# And a third item
; This is a term that is being defined
: This is the definition of that term
}}}
Note that lists can be nested arbitrarily:
{{{
#** One
#* Two
#** Three
#**** Four
#**# Five
#**## Six
## Seven
### Eight
## Nine
}}}
A CSS class can be applied to a list item as follows:
{{{
* List item one
*.active List item two has the class `active`
* List item three
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "list";
exports.blockParser = true;
exports.regExpString = "[\\*#;:]+";
var listTypes = {
"*": {listTag: "ul", itemTag: "li"},
"#": {listTag: "ol", itemTag: "li"},
";": {listTag: "dl", itemTag: "dt"},
":": {listTag: "dl", itemTag: "dd"}
};
/*
*/
exports.parse = function(match,isBlock) {
var listStack = [], // Array containing list elements for the previous row in the list
t, listInfo, listElement, itemElement, previousRootListTag;
// Cycle through the rows in the list
do {
// Walk through the list markers for the current row
for(t=0; t<match[0].length; t++) {
listInfo = listTypes[match[0].charAt(t)];
// Remove any stacked up element if we can't re-use it because the list type doesn't match
if(listStack.length > t && listStack[t].type !== listInfo.listTag) {
listStack.splice(t,listStack.length - t);
}
// Construct the list element or reuse the previous one at this level
if(listStack.length <= t) {
listElement = $tw.Tree.Element(listInfo.listTag,{},[$tw.Tree.Element(listInfo.itemTag,{},[])]);
// Link this list element into the last child item of the parent list item
if(t) {
var prevListItem = listStack[t-1].children[listStack[t-1].children.length-1];
prevListItem.children.push(listElement);
}
// Save this element in the stack
listStack[t] = listElement;
} else if(t === (match[0].length - 1)) {
listStack[t].children.push($tw.Tree.Element(listInfo.itemTag,{},[]));
}
}
if(listStack.length > match[0].length) {
listStack.splice(match[0].length,listStack.length - match[0].length);
}
// Skip the list markers
this.pos = match.index + match[0].length;
// Process the body of the list item into the last list item
var lastListInfo = listTypes[match[0].charAt(match[0].length-1)],
lastListChildren = listStack[listStack.length-1].children,
lastListItem = lastListChildren[lastListChildren.length-1],
classedRun = this.parseClassedRun(/(\r?\n)/mg);
for(t=0; t<classedRun.tree.length; t++) {
lastListItem.children.push(classedRun.tree[t]);
}
if(classedRun["class"]) {
lastListItem.addClass(classedRun["class"]);
}
// Remember the root list tag of this list item
previousRootListTag = listStack[0].type;
// Consume any whitespace following the list item
this.skipWhitespace();
// Lookahead to see if the next line is part of the same list
var nextListItemRegExp = /(^[\*#;:]+)/mg;
nextListItemRegExp.lastIndex = this.pos;
match = nextListItemRegExp.exec(this.source);
listInfo = match ? listTypes[match[0].charAt(0)] : null;
} while(match && match.index === this.pos && listInfo && previousRootListTag === listInfo.listTag);
// Return the root element of the list
return [listStack[0]];
};
})();

View File

@ -1,64 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/macro.js
type: application/javascript
module-type: wikitextrule
Wiki text rule for macros
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "macro";
exports.runParser = true;
exports.blockParser = true;
exports.regExpString = "<<(?:(?:[!@£\\$%\\^\\&\\*\\(\\)`\\~'\"\\|\\\\\\/;\\:\\.\\,\\+\\=\\-\\_\\{\\}])|(?:[^>\\s]+))(?:\\s*)(?:(?:[^>]|(?:>(?!>|<)))*)>(?:>|<)";
exports.parse = function(match,isBlock) {
var regExp = /<<(?:([!@£\$%\^\&\*\(\)`\~'"\|\\\/;\:\.\,\+\=\-\_\{\}])|([^>\s]+))(?:\s*)((?:[^>]|(?:>(?!>|<)))*)>(?:(>)|(<))/mg,
reLineBreak = /(\r?\n)/mg,
content = [];
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
if(match[5]) {
// Look for a line break immediately after the `><` to trigger block mode
reLineBreak.lastIndex = this.pos;
var lineBreakMatch = reLineBreak.exec(this.source);
if(lineBreakMatch && lineBreakMatch.index === this.pos) {
this.pos = lineBreakMatch.index + lineBreakMatch[0].length;
isBlock = true;
} else {
isBlock = false;
}
// If the macro has content then parse it as a block or run
if(isBlock) {
content = this.parseBlocks(">>");
} else {
content = this.parseRun(/(>>)/mg);
}
}
var macroName = match[1] || match[2];
if(macroName in $tw.wiki.macros) {
var macroNode = $tw.Tree.Macro(match[1] || match[2],{
srcParams: match[3],
content: content,
isBlock: isBlock,
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode];
} else {
console.log("Missing macro '" + macroName + "'");
}
}
return [];
};
})();

View File

@ -1,46 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/prettylink.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for pretty links. For example:
{{{
[[Introduction]]
[[Link description|TiddlerTitle]]
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "prettylink";
exports.runParser = true;
exports.regExpString = "\\[\\[";
exports.parse = function(match,isBlock) {
var regExp = /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg;
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match && match.index === this.pos) {
var text = match[1],
link = match[3] || text;
this.pos = match.index + match[0].length;
var macroNode = $tw.Tree.Macro("link",{
srcParams: {to: link},
content: [$tw.Tree.Text(text)],
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode];
}
return [];
};
})();

View File

@ -1,30 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/rule.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for rules. For example:
{{{
---
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "rule";
exports.blockParser = true;
exports.regExpString = "-{3,}\r?\n";
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
return [$tw.Tree.Element("hr",{},[])];
};
})();

View File

@ -1,58 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/styleblock.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for assigning classes to paragraphs and other blocks. For example:
{{{
{{myClass{
This paragraph will have the CSS class `myClass`.
* The `<ul>` around this list will also have the class `myClass`
* List item 2
}}}
}}}
Note that the opening and closing braces both must be immediately followed by a newline.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "style";
exports.blockParser = true;
exports.regExpString = "@@[a-zA-Z0-9_\\-]+:.*;$";
exports.parse = function(match,isBlock) {
var styles = {},
tree = [],
reStyleSpecififer = /@@([a-zA-Z0-9_\-]+):(.*);((?:\r?\n)?)/mg,
reEndString = "@@",
endMatch;
// Look for the first style specifier
reStyleSpecififer.lastIndex = this.pos;
match = reStyleSpecififer.exec(this.source);
while(match && match.index === this.pos) {
// Save the style specified
styles[match[1]] = match[2].trim();
// Look to see if there is a further style specifier
this.pos = match.index + match[0].length;
reStyleSpecififer.lastIndex = this.pos;
match = reStyleSpecififer.exec(this.source);
}
// Parse until we get to the end marker
tree = this.parseBlocks(reEndString);
for(var t=0; t<tree.length; t++) {
tree[t].addStyles(styles);
}
return tree;
};
})();

View File

@ -1,159 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/table.js
type: application/javascript
module-type: wikitextrule
Wiki text block rule for tables.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "table";
exports.blockParser = true;
exports.regExpString = "^\\|(?:[^\\n]*)\\|(?:[fhck]?)\\r?\\n";
var processRow = function(prevColumns) {
var cellRegExp = /(?:\|([^\n\|]*)\|)|(\|[fhck]?\r?\n)/mg,
cellTermRegExp = /((?:\x20*)\|)/mg,
tree = [],
col = 0,
colSpanCount = 1,
prevCell;
// Match a single cell
cellRegExp.lastIndex = this.pos;
var cellMatch = cellRegExp.exec(this.source);
while(cellMatch && cellMatch.index === this.pos) {
if(cellMatch[1] === "~") {
// Rowspan
var last = prevColumns[col];
if(last) {
last.rowSpanCount++;
last.element.attributes.rowspan = last.rowSpanCount;
last.element.attributes.valign = "center";
if(colSpanCount > 1) {
last.element.attributes.colspan = colSpanCount;
colSpanCount = 1;
}
}
// Move to just before the `|` terminating the cell
this.pos = cellRegExp.lastIndex - 1;
} else if(cellMatch[1] === ">") {
// Colspan
colSpanCount++;
// Move to just before the `|` terminating the cell
this.pos = cellRegExp.lastIndex - 1;
} else if(cellMatch[2]) {
// End of row
if(prevCell && colSpanCount > 1) {
prevCell.attributes.colspan = colSpanCount;
}
this.pos = cellRegExp.lastIndex - 1;
break;
} else {
// For ordinary cells, step beyond the opening `|`
this.pos++;
// Look for a space at the start of the cell
var spaceLeft = false,
chr = this.source.substr(this.pos,1);
while(chr === " ") {
spaceLeft = true;
this.pos++;
chr = this.source.substr(this.pos,1);
}
// Check whether this is a heading cell
var cell;
if(chr === "!") {
this.pos++;
cell = $tw.Tree.Element("th",{},[]);
} else {
cell = $tw.Tree.Element("td",{},[]);
}
tree.push(cell);
// Record information about this cell
prevCell = cell;
prevColumns[col] = {rowSpanCount:1,element:cell};
// Check for a colspan
if(colSpanCount > 1) {
cell.attributes.colspan = colSpanCount;
colSpanCount = 1;
}
// Parse the cell
cell.children = this.parseRun(cellTermRegExp);
// Set the alignment for the cell
if(cellMatch[1].substr(cellMatch[1].length-1,1) === " ") { // spaceRight
cell.attributes.align = spaceLeft ? "center" : "left";
} else if(spaceLeft) {
cell.attributes.align = "right";
}
// Move back to the closing `|`
this.pos--;
}
col++;
cellRegExp.lastIndex = this.pos;
cellMatch = cellRegExp.exec(this.source);
}
return tree;
};
exports.parse = function(match,isBlock) {
var rowContainerTypes = {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
table = $tw.Tree.Element("table",{"class": ["table"]},[]),
rowRegExp = /^\|([^\n]*)\|([fhck]?)\r?\n/mg,
rowTermRegExp = /(\|(?:[fhck]?)\r?\n)/mg,
prevColumns = [],
currRowType,
rowContainer,
rowCount = 0;
// Match the row
rowRegExp.lastIndex = this.pos;
var rowMatch = rowRegExp.exec(this.source);
while(rowMatch && rowMatch.index === this.pos) {
var rowType = rowMatch[2];
// Check if it is a class assignment
if(rowType === "k") {
table.attributes["class"].push(rowMatch[1]);
this.pos = rowMatch.index + rowMatch[0].length;
} else {
// Otherwise, create a new row if this one is of a different type
if(rowType != currRowType) {
rowContainer = $tw.Tree.Element(rowContainerTypes[rowType],{},[]);
table.children.push(rowContainer);
currRowType = rowType;
}
// Is this a caption row?
if(currRowType === "c") {
// If so, move past the opening `|` of the row
this.pos++;
// Move the caption to the first row if it isn't already
if(table.children.length !== 1) {
table.children.pop(); // Take rowContainer out of the children array
table.children.splice(0,0,rowContainer); // Insert it at the bottom
}
// Set the alignment - TODO: figure out why TW did this
rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
// Parse the caption
rowContainer.children = this.parseRun(rowTermRegExp);
} else {
// Create the row
var theRow = $tw.Tree.Element("tr",{},[]);
theRow.attributes["class"] = rowCount%2 ? "oddRow" : "evenRow";
rowContainer.children.push(theRow);
// Process the row
theRow.children = processRow.call(this,prevColumns);
this.pos = rowMatch.index + rowMatch[0].length;
// Increment the row count
rowCount++;
}
}
rowMatch = rowRegExp.exec(this.source);
}
return [table];
};
})();

View File

@ -1,53 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/transclude.js
type: application/javascript
module-type: wikitextrule
Wiki text rule for transclusion. For example:
{{{
{{MyTiddler}}
{{MyTiddler}{MyTemplate}}
{{MyTiddler}Template <<view text>>}
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "transclude";
exports.runParser = true;
exports.blockParser = true;
exports.regExpString = "\\{\\{(?:(?:[^\\{\\}]+)|(?:\\{[^\\{\\}]+\\}))\\}(?:\\{[^\\}]+\\}|(?:[^\\}]+))?\\}";
exports.parse = function(match,isBlock) {
var regExp = /\{\{([^\{\}]+)\}(?:\{([^\}]+)\}|([^\}]+))?\}((?:\r?\n)?)/mg;
regExp.lastIndex = this.pos;
match = regExp.exec(this.source);
if(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
var macro, params = {}, parseTree;
if(match[1]) {
params.target = match[1];
}
if(match[2]) {
params.template = match[2];
}
if(match[3]) {
parseTree = this.wiki.parseText("text/vnd.tiddlywiki",match[3]).tree;
}
return [$tw.Tree.Macro("tiddler",{
srcParams: params,
wiki: this.wiki,
content: parseTree
})];
}
return [];
};
})();

View File

@ -1,59 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/typedblock.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for typed blocks. For example:
{{{
$$$.js
This will be rendered as JavaScript
$$$
$$$.svg
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
$$$
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "typedblock";
exports.blockParser = true;
exports.regExpString = "\\$\\$\\$(?:.*)\\r?\\n";
exports.parse = function(match,isBlock) {
var startRegExp = /\$\$\$(.*)\r?\n/mg,
endRegExp = /^(\$\$\$)$/mg;
startRegExp.lastIndex = this.pos;
match = startRegExp.exec(this.source);
if(match) {
var mimeType = match[1],
text;
this.pos = match.index + match[0].length;
endRegExp.lastIndex = this.pos;
match = endRegExp.exec(this.source);
if(match) {
text = this.source.substring(this.pos,match.index);
this.pos = match.index + match[0].length;
} else {
text = this.source.substr(this.pos);
this.pos = this.sourceLength;
}
var renderer = this.wiki.parseText(mimeType,text,{defaultType: "text/plain"});
this.dependencies.mergeDependencies(renderer.dependencies);
return renderer.tree;
} else {
return [];
}
};
})();

View File

@ -1,66 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/rules/wikilink.js
type: application/javascript
module-type: wikitextrule
Wiki text run rule for wiki links. For example:
{{{
AWikiLink
AnotherLink
~SuppressedLink
}}}
Precede a camel case word with `~` to prevent it from being recognised as a link.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "wikilink";
exports.runParser = true;
var 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]"
};
textPrimitives.unWikiLink = "~";
textPrimitives.wikiLink = textPrimitives.upperLetter + "+" +
textPrimitives.lowerLetter + "+" +
textPrimitives.upperLetter +
textPrimitives.anyLetter + "*";
exports.regExpString = textPrimitives.unWikiLink + "?" + textPrimitives.wikiLink;
exports.parse = function(match,isBlock) {
this.pos = match.index + match[0].length;
// If the link starts with the unwikilink character then just output it as plain text
if(match[0].substr(0,1) === textPrimitives.unWikiLink) {
return [$tw.Tree.Text(match[0].substr(1))];
}
// If the link has been preceded with a letter then don't treat it as a link
if(match.index > 0) {
var preRegExp = new RegExp(textPrimitives.anyLetterStrict,"mg");
preRegExp.lastIndex = match.index-1;
var preMatch = preRegExp.exec(this.source);
if(preMatch && preMatch.index === match.index-1) {
return [$tw.Tree.Text(match[0])];
}
}
var macroNode = $tw.Tree.Macro("link",{
srcParams: {to: match[0]},
content: [$tw.Tree.Text(match[0])],
wiki: this.wiki
});
this.dependencies.mergeDependencies(macroNode.dependencies);
return [macroNode];
};
})();

View File

@ -1,300 +0,0 @@
/*\
title: $:/core/modules/parsers/wikitextparser/wikitextparser.js
type: application/javascript
module-type: parser
A new-school wikitext parser
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Define the wikitext renderer constructor
*/
var WikiTextRenderer = function(text,options) {
this.source = text || "";
this.sourceLength = this.source.length;
this.pos = 0;
this.wiki = options.wiki;
this.parser = options.parser;
this.tree = [];
this.dependencies = new $tw.Dependencies();
// Parse the text into runs or blocks
if(options.isRun) {
this.tree.push.apply(this.tree,this.parseRun());
} else {
this.tree.push.apply(this.tree,this.parseBlocks());
}
};
/*
Now make WikiTextRenderer inherit from the default Renderer class
*/
var Renderer = require("$:/core/modules/renderer.js").Renderer;
WikiTextRenderer.prototype = new Renderer();
WikiTextRenderer.constructor = WikiTextRenderer;
/*
Parse a block from the current position
terminatorRegExpString: optional regular expression string that identifies the end of plain paragraphs. Must not include capturing parenthesis
options: see below
Options are:
leaveTerminator: True if the terminator shouldn't be consumed
*/
WikiTextRenderer.prototype.parseBlock = function(terminatorRegExpString,options) {
var terminatorRegExp = terminatorRegExpString ? new RegExp("(" + terminatorRegExpString + "|\\r?\\n\\r?\\n)","mg") : /(\r?\n\r?\n)/mg;
this.skipWhitespace();
if(this.pos >= this.sourceLength) {
return [];
}
// Look for a block rule
this.parser.blockRegExp.lastIndex = this.pos;
var match = this.parser.blockRegExp.exec(this.source);
if(this.parser.blockRules.length && match && match.index === this.pos) {
var rule;
for(var t=0; t<this.parser.blockRules.length; t++) {
if(match[t+1]) {
rule = this.parser.blockRules[t];
}
}
return rule ? rule.parse.call(this,match,true) : [];
} else {
// Treat it as a paragraph if we didn't find a block rule
return [$tw.Tree.Element("p",{},this.parseRun(terminatorRegExp,options))];
}
};
/*
Parse blocks of text until a terminating regexp is encountered or the end of the text
terminatorRegExpString: terminating regular expression
options: none at present
*/
WikiTextRenderer.prototype.parseBlocks = function(terminatorRegExpString,options) {
if(terminatorRegExpString) {
return this.parseBlocksTerminated(terminatorRegExpString,options);
} else {
return this.parseBlocksUnterminated(options);
}
};
/*
Parse a block from the current position to the end of the text
*/
WikiTextRenderer.prototype.parseBlocksUnterminated = function(options) {
var tree = [];
while(this.pos < this.sourceLength) {
tree.push.apply(tree,this.parseBlock());
}
return tree;
};
/*
Parse blocks of text until a terminating regexp is encountered. See parseBlocks() for details
*/
WikiTextRenderer.prototype.parseBlocksTerminated = function(terminatorRegExpString,options) {
options = options || {};
var terminatorRegExp = new RegExp("(" + terminatorRegExpString + ")","mg"),
tree = [];
// Skip any whitespace
this.skipWhitespace();
// Check if we've got the end marker
terminatorRegExp.lastIndex = this.pos;
var match = terminatorRegExp.exec(this.source);
// Parse the text into blocks
while(this.pos < this.sourceLength && !(match && match.index === this.pos)) {
var blocks = this.parseBlock(terminatorRegExpString,{leaveTerminator: true});
tree.push.apply(tree,blocks);
// Skip any whitespace
this.skipWhitespace();
// Check if we've got the end marker
terminatorRegExp.lastIndex = this.pos;
match = terminatorRegExp.exec(this.source);
}
if(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
}
return tree;
};
WikiTextRenderer.prototype.skipWhitespace = function() {
var whitespaceRegExp = /(\s+)/mg;
whitespaceRegExp.lastIndex = this.pos;
var whitespaceMatch = whitespaceRegExp.exec(this.source);
if(whitespaceMatch && whitespaceMatch.index === this.pos) {
this.pos = whitespaceRegExp.lastIndex;
}
};
/*
Parse a run of text at the current position
terminatorRegExp: a regexp at which to stop the run
options: see below
Options are:
leaveTerminator: true if the terminator shouldn't be consumed
Returns an array of tree nodes
*/
WikiTextRenderer.prototype.parseRun = function(terminatorRegExp,options) {
if(terminatorRegExp) {
return this.parseRunTerminated(terminatorRegExp,options);
} else {
return this.parseRunUnterminated(options);
}
};
WikiTextRenderer.prototype.parseRunUnterminated = function(options) {
options = options || {};
var tree = [];
// Find the next occurrence of a runrule
this.parser.runRegExp.lastIndex = this.pos;
var runRuleMatch = this.parser.runRegExp.exec(this.source);
// Loop around until we've reached the end of the text
while(this.pos < this.sourceLength && runRuleMatch) {
// Process the text preceding the run rule
if(runRuleMatch.index > this.pos) {
tree.push($tw.Tree.Text(this.source.substring(this.pos,runRuleMatch.index)));
this.pos = runRuleMatch.index;
}
// Process the run rule
var rule;
for(var t=0; t<this.parser.runRules.length; t++) {
if(runRuleMatch[t+1]) {
rule = this.parser.runRules[t];
}
}
if(rule) {
tree.push.apply(tree,rule.parse.call(this,runRuleMatch,false));
}
// Look for the next run rule
this.parser.runRegExp.lastIndex = this.pos;
runRuleMatch = this.parser.runRegExp.exec(this.source);
}
// Process the remaining text
if(this.pos < this.sourceLength) {
tree.push($tw.Tree.Text(this.source.substr(this.pos)));
}
this.pos = this.sourceLength;
return tree;
};
WikiTextRenderer.prototype.parseRunTerminated = function(terminatorRegExp,options) {
options = options || {};
var tree = [];
// Find the next occurrence of the terminator
terminatorRegExp.lastIndex = this.pos;
var terminatorMatch = terminatorRegExp.exec(this.source);
// Find the next occurrence of a runrule
this.parser.runRegExp.lastIndex = this.pos;
var runRuleMatch = this.parser.runRegExp.exec(this.source);
// Loop around until we've reached the end of the text
while(this.pos < this.sourceLength && (terminatorMatch || runRuleMatch)) {
// Return if we've found the terminator, and it precedes any run rule match
if(terminatorMatch) {
if(!runRuleMatch || runRuleMatch.index >= terminatorMatch.index) {
if(terminatorMatch.index > this.pos) {
tree.push($tw.Tree.Text(this.source.substring(this.pos,terminatorMatch.index)));
}
this.pos = terminatorMatch.index;
if(!options.leaveTerminator) {
this.pos += terminatorMatch[0].length;
}
return tree;
}
}
// Process any run rule, along with the text preceding it
if(runRuleMatch) {
// Preceding text
if(runRuleMatch.index > this.pos) {
tree.push($tw.Tree.Text(this.source.substring(this.pos,runRuleMatch.index)));
this.pos = runRuleMatch.index;
}
// Process the run rule
var rule;
for(var t=0; t<this.parser.runRules.length; t++) {
if(runRuleMatch[t+1]) {
rule = this.parser.runRules[t];
}
}
if(rule) {
tree.push.apply(tree,rule.parse.call(this,runRuleMatch,false));
}
// Look for the next run rule and the next terminator match
this.parser.runRegExp.lastIndex = this.pos;
runRuleMatch = this.parser.runRegExp.exec(this.source);
terminatorRegExp.lastIndex = this.pos;
terminatorMatch = terminatorRegExp.exec(this.source);
}
}
// Process the remaining text
if(this.pos < this.sourceLength) {
tree.push($tw.Tree.Text(this.source.substr(this.pos)));
}
this.pos = this.sourceLength;
return tree;
};
/*
Parse a run of text preceded by an optional class specifier `.classname`
*/
WikiTextRenderer.prototype.parseClassedRun = function(terminatorRegExp) {
var classRegExp = /\.([^\s\.]+)/mg,
classNames = [];
classRegExp.lastIndex = this.pos;
var match = classRegExp.exec(this.source);
while(match && match.index === this.pos) {
this.pos = match.index + match[0].length;
classNames.push(match[1]);
var match = classRegExp.exec(this.source);
}
var tree = this.parseRun(terminatorRegExp);
return {
"class": classNames.join(" "),
tree: tree
};
};
/*
The wikitext parser assembles the rules and uses the wikitext renderer to do the parsing
*/
var WikiTextParser = function(options) {
this.wiki = options.wiki;
// Assemble the rule regexps
this.blockRules = [];
this.runRules = [];
var blockRegExpStrings = [],
runRegExpStrings = [],
self = this;
$tw.modules.forEachModuleOfType("wikitextrule",function(title,module) {
if(module.blockParser) {
self.blockRules.push(module);
blockRegExpStrings.push("(" + module.regExpString + ")");
}
if(module.runParser) {
self.runRules.push(module);
runRegExpStrings.push("(" + module.regExpString + ")");
}
});
this.blockRegExp = new RegExp(blockRegExpStrings.join("|"),"mg");
this.runRegExp = new RegExp(runRegExpStrings.join("|"),"mg");
};
/*
The wikitext parser constructs a wikitext renderer to do the work
*/
WikiTextParser.prototype.parse = function(type,text) {
return new WikiTextRenderer(text,{
wiki: this.wiki,
parser: this,
isRun: type === "text/vnd.tiddlywiki-run"
});
};
exports["text/vnd.tiddlywiki"] = WikiTextParser;
exports["text/vnd.tiddlywiki-run"] = WikiTextParser;
})();

View File

@ -0,0 +1,35 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/commentblock.js
type: application/javascript
module-type: wikirule
Wiki text block rule for HTML comments. For example:
```
<!-- This is a comment -->
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "commentblock";
exports.types = {block: true};
exports.init = function(parser) {
this.parser = parser;
// Regexp to match - HTML comment regexp by Stephen Ostermiller, http://ostermiller.org/findhtmlcomment.html
this.matchRegExp = /\<![ \r\n\t]*(?:--(?:[^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>\r?\n/mg;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Don't return any elements
return [];
};
})();

View File

@ -1,5 +1,5 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/comment.js
title: $:/core/modules/parsers/wikiparser/rules/commentinline.js
type: application/javascript
module-type: wikirule
@ -16,7 +16,7 @@ Wiki text inline rule for HTML comments. For example:
/*global $tw: false */
"use strict";
exports.name = "comment";
exports.name = "commentinline";
exports.types = {inline: true};
exports.init = function(parser) {

View File

@ -42,7 +42,7 @@ exports.init = function(parser) {
};
exports.parse = function() {
var reEndString = "$@@(?:\\r?\\n)?";
var reEndString = "^@@(?:\\r?\\n)?";
var classes = [], styles = [];
do {
// Get the class and style

View File

@ -1,48 +0,0 @@
/*\
title: $:/core/modules/renderer.js
type: application/javascript
module-type: global
Represents a parse tree and associated data
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Renderer = function(tree,dependencies) {
this.tree = tree;
this.dependencies = dependencies;
};
Renderer.prototype.execute = function(parents,tiddlerTitle) {
for(var t=0; t<this.tree.length; t++) {
this.tree[t].execute(parents,tiddlerTitle);
}
};
Renderer.prototype.render = function(type) {
var output = [];
for(var t=0; t<this.tree.length; t++) {
output.push(this.tree[t].render(type));
}
return output.join("");
};
Renderer.prototype.renderInDom = function(parentDomNode,insertBefore) {
for(var t=0; t<this.tree.length; t++) {
this.tree[t].renderInDom(parentDomNode,insertBefore);
}
};
Renderer.prototype.refreshInDom = function(changes) {
for(var t=0; t<this.tree.length; t++) {
this.tree[t].refreshInDom(changes);
}
};
exports.Renderer = Renderer;
})();

View File

@ -32,7 +32,7 @@ var MacroCallRenderer = function(renderTree,renderContext,parseTreeNode) {
// Substitute the macro parameters
var text = this.substituteParameters(macro.text,this.parseTreeNode,macro);
// Parse the text
childTree = this.renderTree.wiki.new_parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.parseTreeNode.isBlock}).tree;
childTree = this.renderTree.wiki.parseText("text/vnd.tiddlywiki",text,{parseAsInline: !this.parseTreeNode.isBlock}).tree;
}
// Create the renderers for the child nodes
this.children = this.renderTree.createRenderers(this.renderContext,childTree);

View File

@ -1,182 +0,0 @@
/*\
title: $:/core/modules/serializers.js
type: application/javascript
module-type: tiddlerserializer
Functions to serialise tiddlers to a block of text
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Helper function
var mapEachTiddler = function(wiki,tiddlers,callback) {
var result = [];
for(var t=0; t<tiddlers.length; t++) {
var tiddler = tiddlers[t];
if(tiddler) {
result.push(callback.call(wiki,tiddler));
}
}
return result.join("");
};
exports["text/plain"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
return tiddler.fields.text;
});
};
exports["text/html"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
return this.renderTiddler("text/html",tiddler.fields.title);
});
};
exports["application/x-tiddler"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
return tiddler.getFieldStringBlock({exclude: ["text"]}) + "\n\n" + tiddler.fields.text;
});
};
exports["application/x-tiddler-css"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
var attributes = {type: "text/css"}; // The script type is set to text/javascript for compatibility with old browsers
for(var f in tiddler.fields) {
if(f !== "text") {
attributes["data-tiddler-" + f] = tiddler.getFieldString(f);
}
}
return $tw.Tree.Element(
"style",
attributes,
[$tw.Tree.Raw(tiddler.fields.text)]
).render("text/html");
});
};
exports["application/javascript"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
var attributes = {type: "text/javascript"}; // The script type is set to text/javascript for compatibility with old browsers
for(var f in tiddler.fields) {
if(f !== "text") {
attributes["data-tiddler-" + f] = tiddler.getFieldString(f);
}
}
return $tw.Tree.Element(
"script",
attributes,
[$tw.Tree.Raw(tiddler.fields.text)]
).render("text/html");
});
};
exports["application/x-tiddler-module"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
var attributes = {
type: "text/javascript",
"data-module": "yes"
}, // The script type is set to text/javascript for compatibility with old browsers
text = tiddler.fields.text;
text = "$tw.modules.define(\"" + tiddler.fields.title + "\",\"" + tiddler.fields["module-type"] + "\",function(module,exports,require) {" + text + "});\n";
for(var f in tiddler.fields) {
if(f !== "text") {
attributes["data-tiddler-" + f] = tiddler.getFieldString(f);
}
}
return $tw.Tree.Element(
"script",
attributes,
[$tw.Tree.Raw(text)]
).render("text/html");
});
};
exports["application/x-tiddler-module-plain"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
return "$tw.modules.define(\"" + tiddler.fields.title + "\",\"" + tiddler.fields["module-type"] + "\",function(module,exports,require) {" + tiddler.fields.text + "});\n";
});
};
exports["application/x-tiddler-library"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
var attributes = {
type: "text/javascript"
}, // The script type is set to text/javascript for compatibility with old browsers
text = tiddler.fields.text;
for(var f in tiddler.fields) {
if(f !== "text") {
attributes["data-tiddler-" + f] = tiddler.getFieldString(f);
}
}
return $tw.Tree.Element(
"script",
attributes,
[$tw.Tree.Raw(text)]
).render("text/html");
});
};
exports["application/x-tiddler-html-div"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
var result = [],
fields = [],
pullField = function(name) {
var fieldIndex = fields.indexOf(name);
if(fieldIndex !== -1) {
fields.splice(fieldIndex,1);
fields.unshift(name);
}
};
result.push("<div");
// Collect the field names in the tiddler
for(var f in tiddler.fields) {
if(f !== "text") {
fields.push(f);
}
}
// Sort the fields
fields.sort();
// Pull the standard fields up to the top
pullField("tags");
pullField("modified");
pullField("created");
pullField("modifier");
pullField("creator");
pullField("title");
// Output the fields
for(f=0; f<fields.length; f++) {
result.push(" " + fields[f] + "=\"" + $tw.utils.htmlEncode(tiddler.getFieldString(fields[f])) + "\"");
}
result.push(">\n<pre>");
result.push($tw.utils.htmlEncode(tiddler.fields.text));
result.push("</pre>\n</div>");
return result.join("");
});
};
exports["application/x-tiddler-encrypted-div"] = function(tiddlers) {
// Build up the JSON object representing the tiddlers
var jsonTiddlers = {},
t, f;
for(t=0; t<tiddlers.length; t++) {
var tiddler = tiddlers[t],
jsonTiddler = jsonTiddlers[tiddler.fields.title] = {};
for(f in tiddler.fields) {
jsonTiddler[f] = tiddler.getFieldString(f);
}
}
// Encrypt the JSON of the tiddlers
return "<div data-tw-encrypted-tiddlers='yes'><pre>" + $tw.utils.htmlEncode($tw.crypto.encrypt(JSON.stringify(jsonTiddlers))) + "</pre></div>";
};
exports["application/x-tiddler-javascript"] = function(tiddlers) {
return mapEachTiddler(this,tiddlers,function(tiddler) {
return "$tw.preloadTiddler(" + JSON.stringify(tiddler.fields) + ");\n";
});
};
})();

View File

@ -28,13 +28,7 @@ exports.startup = function() {
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.Wiki.tiddlerSerializerModules = {};
$tw.modules.applyMethods("tiddlerserializer",$tw.Wiki.tiddlerSerializerModules);
$tw.modules.applyMethods("treeutils",$tw.Tree);
$tw.modules.applyMethods("treenode",$tw.Tree);
// Set up the wiki store
$tw.wiki.initMacros();
$tw.wiki.initEditors();
$tw.wiki.initFieldViewers();
$tw.wiki.initListViews();
$tw.wiki.initParsers();
$tw.wiki.initSyncers();
$tw.wiki.initServerConnections();
@ -99,13 +93,16 @@ exports.startup = function() {
document.dispatchEvent(event);
}
// Display the PageTemplate
var template = "$:/templates/PageTemplate",
title = template;
$tw.renderer = $tw.wiki.parseTiddler(template);
$tw.renderer.execute([],title);
$tw.renderer.renderInDom(document.body);
var templateTitle = "$:/templates/PageTemplate",
parser = $tw.wiki.parseTiddler(templateTitle),
renderTree = new $tw.WikiRenderTree(parser,{wiki: $tw.wiki});
console.log("Parse tree",parser);
renderTree.execute({tiddlerTitle: templateTitle});
var container = document.createElement("div");
document.body.insertBefore(container,document.body.firstChild);
renderTree.renderInDom(container);
$tw.wiki.addEventListener("",function(changes) {
$tw.renderer.refreshInDom(changes);
renderTree.refreshInDom(changes);
});
} else {
// On the server, start a commander with the command line arguments

View File

@ -1,33 +0,0 @@
/*\
title: $:/core/modules/testnewwikiparser.js
type: application/javascript
module-type: global
Test the new parser
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var testNewParser = function() {
var templateTitle = "$:/templates/NewPageTemplate";
var parser = $tw.wiki.new_parseTiddler(templateTitle);
console.log("parsetree after execution",parser);
var renderTree = new $tw.WikiRenderTree(parser,{wiki: $tw.wiki});
renderTree.execute({tiddlerTitle: templateTitle});
console.log("html rendering:",renderTree.render("text/html"));
console.log("renderTree after execution",renderTree);
var container = document.createElement("div");
document.body.insertBefore(container,document.body.firstChild);
renderTree.renderInDom(container);
$tw.wiki.addEventListener("",function(changes) {
renderTree.refreshInDom(changes);
});
};
exports.testNewParser = testNewParser;
})();

View File

@ -1,28 +0,0 @@
/*\
title: $:/core/modules/tree.js
type: application/javascript
module-type: global
Renderer objects encapsulate a tree of nodes that are capable of rendering and selectively updating an
HTML representation of themselves. The following node types are defined:
* ''Macro'' - represents an invocation of a macro
* ''Element'' - represents a single HTML element
* ''Text'' - represents an HTML text node
* ''Entity'' - represents an HTML entity node
* ''Raw'' - represents a chunk of unparsed HTML text
These node types are implemented with prototypal inheritance from a base Node class. One
unusual convenience in the implementation is that the node constructors can be called without an explicit
`new` keyword: the constructors check for `this` not being an instance of themselves, and recursively invoke
themselves with `new` when required.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.Tree = {};
})();

View File

@ -1,57 +0,0 @@
/*\
title: $:/core/modules/tree.utils.js
type: application/javascript
module-type: treeutils
Static utility methods for the $tw.Tree class
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Construct an error message
*/
exports.errorNode = function(text) {
return $tw.Tree.Element("span",{
"class": ["label","label-important"]
},[
new $tw.Tree.Text(text)
]);
};
/*
Construct a label
*/
exports.labelNode = function(type,value,classes) {
classes = (classes || []).slice(0);
classes.push("label");
return $tw.Tree.Element("span",{
"class": classes,
"data-tw-label-type": type
},value);
};
/*
Construct a split label
*/
exports.splitLabelNode = function(type,left,right,classes) {
classes = (classes || []).slice(0);
classes.push("splitLabel");
return $tw.Tree.Element("span",{
"class": classes
},[
$tw.Tree.Element("span",{
"class": ["splitLabelLeft"],
"data-tw-label-type": type
},left),
$tw.Tree.Element("span",{
"class": ["splitLabelRight"]
},right)
]);
};
})();

View File

@ -1,170 +0,0 @@
/*\
title: $:/core/modules/treenodes/element.js
type: application/javascript
module-type: treenode
Element nodes
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Node = require("./node.js").Node;
var Element = function(type,attributes,children,options) {
options = options || {};
if(this instanceof Element) {
this.type = type;
this.attributes = attributes || {};
this.children = children;
this.events = options.events;
this.eventHandler = options.eventHandler;
} else {
return new Element(type,attributes,children,options);
}
};
Element.prototype = new Node();
Element.prototype.constructor = Element;
Element.prototype.clone = function() {
var childClones;
if(this.children) {
childClones = [];
for(var t=0; t<this.children.length; t++) {
childClones.push(this.children[t].clone());
}
}
return new Element(this.type,this.attributes,childClones,{
events: this.events,
eventHandler: this.eventHandler
});
};
Element.prototype.execute = function(parents,tiddlerTitle) {
if(this.children) {
for(var t=0; t<this.children.length; t++) {
this.children[t].execute(parents,tiddlerTitle);
}
}
};
Element.prototype.render = function(type) {
var isHtml = type === "text/html",
output = [],attr,a,v;
if(isHtml) {
output.push("<",this.type);
if(this.attributes) {
attr = [];
for(a in this.attributes) {
attr.push(a);
}
attr.sort();
for(a=0; a<attr.length; a++) {
v = this.attributes[attr[a]];
if(v !== undefined) {
if($tw.utils.isArray(v)) {
v = v.join(" ");
} else if(typeof v === "object") {
var s = [];
for(var p in v) {
s.push(p + ":" + v[p] + ";");
}
v = s.join("");
}
output.push(" ",attr[a],"='",$tw.utils.htmlEncode(v),"'");
}
}
}
output.push(">");
}
if(this.children) {
for(var t=0; t<this.children.length; t++) {
output.push(this.children[t].render(type));
}
if(isHtml) {
output.push("</",this.type,">");
}
}
return output.join("");
};
Element.prototype.renderInDom = function(parentDomNode,insertBefore) {
// Create the element
var element = document.createElement(this.type);
// Assign the attributes
if(this.attributes) {
for(var a in this.attributes) {
var v = this.attributes[a];
if(v !== undefined) {
if($tw.utils.isArray(v)) { // Ahem, could there be arrays other than className?
element.className = v.join(" ");
} else if (typeof v === "object") { // ...or objects other than style?
for(var p in v) {
element.style[$tw.utils.unHyphenateCss(p)] = v[p];
}
} else {
element.setAttribute(a,v);
}
}
}
}
// Insert it into the DOM tree
if(insertBefore) {
parentDomNode.insertBefore(element,insertBefore);
} else {
parentDomNode.appendChild(element);
}
// Register event handlers
if(this.events) {
for(var e=0; e<this.events.length; e++) {
element.addEventListener(this.events[e],this.eventHandler,false);
}
}
// Save a reference to the DOM element
this.domNode = element;
// Render any child nodes
if(this.children) {
for(var t=0; t<this.children.length; t++) {
this.children[t].renderInDom(element);
}
}
};
Element.prototype.refresh = function(changes) {
if(this.children) {
for(var t=0; t<this.children.length; t++) {
this.children[t].refresh(changes);
}
}
};
Element.prototype.refreshInDom = function(changes) {
if(this.children) {
for(var t=0; t<this.children.length; t++) {
this.children[t].refreshInDom(changes);
}
}
};
Element.prototype.addClass = function(className) {
if(typeof this.attributes["class"] === "string") {
this.attributes["class"] = this.attributes["class"].split(" ");
}
this.attributes["class"] = this.attributes["class"] || [];
this.attributes["class"].push(className);
};
Element.prototype.addStyles = function(styles) {
this.attributes.style = this.attributes.style || {};
for(var t in styles) {
this.attributes.style[t] = styles[t];
}
};
exports.Element = Element;
})();

View File

@ -1,39 +0,0 @@
/*\
title: $:/core/modules/treenodes/entity.js
type: application/javascript
module-type: treenode
Entity nodes
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Node = require("./node.js").Node;
var Entity = function(entity) {
if(this instanceof Entity) {
this.entity = entity;
} else {
return new Entity(entity);
}
};
Entity.prototype = new Node();
Entity.prototype.constructor = Entity;
Entity.prototype.render = function(type) {
return type === "text/html" ? this.entity : $tw.utils.entityDecode(this.entity);
};
Entity.prototype.renderInDom = function(domNode) {
this.domNode = document.createTextNode($tw.utils.entityDecode(this.entity));
domNode.appendChild(this.domNode);
};
exports.Entity = Entity;
})();

View File

@ -1,242 +0,0 @@
/*\
title: $:/core/modules/treenodes/macro.js
type: application/javascript
module-type: treenode
Macro node, used as the base class for macros
\*/
(function(){
/*jshint node: true, browser: true */
/*global $tw: false */
"use strict";
var Node = require("./node.js").Node;
/*
Construct a renderer node representing a macro invocation
macroName: name of the macro
options: see below
The options available are:
srcParams: a string or a hashmap of parameters (each can be a string, or a fn(tiddler,wiki) for evaluated parameters)
content: optional array of child nodes
wiki: reference to the WikiStore associated with this macro
dependencies: optional Dependencies object representing the dependencies of this macro
isBlock: true if this macro is being used as an HTML block
classes: array of classes to be assigned to the macro
Note that the dependencies will be evaluated if not provided.
*/
var Macro = function(macroName,options) {
options = options || {};
var MacroClass = options.wiki ? options.wiki.macros[macroName] : null; // Get the macro class
if(this instanceof Macro) {
// Save the details
this.macroName = macroName;
this.srcParams = options.srcParams || {};
this.content = options.content || [];
this.wiki = options.wiki;
this.dependencies = options.dependencies;
this.isBlock = options.isBlock;
this.classes = options.classes;
// Parse the macro parameters if required
if(typeof this.srcParams === "string") {
this.srcParams = this.parseMacroParamString(this.srcParams);
}
// Evaluate the dependencies if required
if(macroName && !this.dependencies) {
this.dependencies = this.evaluateDependencies();
}
// Get a reference to the static information about this macro
if(MacroClass) {
this.MacroClass = MacroClass;
this.info = MacroClass.prototype.info;
}
} else {
// If Macro() has been called without 'new' then instantiate the right macro class
if(!MacroClass) {
throw "Unknown macro '" + macroName + "'";
}
return new MacroClass(macroName,options);
}
};
Macro.prototype = new Node();
Macro.prototype.constructor = Macro;
/*
Evaluate the dependencies of this macro invocation. If the macro provides an `evaluateDependencies` method
then it is invoked to evaluate the dependencies. Otherwise it generates the dependencies based on the
macro parameters provided
*/
Macro.prototype.evaluateDependencies = function() {
// Figure out the dependencies from the metadata and parameters
var dependencies = new $tw.Dependencies();
if(this.info.dependentAll) {
dependencies.dependentAll = true;
}
if(this.info.dependentOnContextTiddler) {
dependencies.dependentOnContextTiddler = true;
}
for(var m in this.info.params) {
var paramInfo = this.info.params[m];
if(m in this.srcParams && paramInfo.type === "tiddler") {
if(typeof this.srcParams[m] === "function") {
dependencies.dependentAll = true;
} else {
dependencies.addDependency(this.srcParams[m],!paramInfo.skinny);
}
}
}
return dependencies;
};
Macro.prototype.parseMacroParamString = function(paramString) {
/*jslint evil: true */
var params = {},
args = new $tw.utils.ArgParser(paramString,{defaultName: "anon", cascadeDefaults: this.info.cascadeDefaults}),
self = this,
insertParam = function(name,arg) {
if(arg.evaluated) {
params[name] = eval("(function(tiddler,wiki) {return " + arg.string + ";})");
} else {
params[name] = arg.string;
}
};
for(var m in this.info.params) {
var param = this.info.params[m],
arg;
if("byPos" in param && args.byPos[param.byPos] && (args.byPos[param.byPos].n === "anon" || args.byPos[param.byPos].n === m)) {
arg = args.byPos[param.byPos].v;
insertParam(m,arg);
} else {
arg = args.getValueByName(m);
if(!arg && param.byName === "default") {
arg = args.getValueByName("anon");
}
if(arg) {
insertParam(m,arg);
}
}
}
return params;
};
Macro.prototype.hasParameter = function(name) {
return this.params[name] !== undefined;
};
Macro.prototype.cloneContent = function() {
var contentClones = [];
for(var t=0; t<this.content.length; t++) {
contentClones.push(this.content[t].clone());
}
return contentClones;
};
Macro.prototype.clone = function() {
return new this.MacroClass(this.macroName,{
srcParams: this.srcParams,
content: this.cloneContent(),
wiki: this.wiki,
isBlock: this.isBlock,
dependencies: this.dependencies,
classes: this.classes
});
};
Macro.prototype.execute = function(parents,tiddlerTitle) {
parents = parents || [];
// Evaluate macro parameters to get their values
this.params = {};
var tiddler = this.wiki.getTiddler(tiddlerTitle);
if(!tiddler) {
tiddler = {title: tiddlerTitle};
}
for(var p in this.srcParams) {
if(typeof this.srcParams[p] === "function") {
this.params[p] = this.srcParams[p](tiddler.fields,this.wiki);
} else {
this.params[p] = this.srcParams[p];
}
}
// Save the context info for use when we're refreshing it
this.tiddlerTitle = tiddlerTitle;
this.parents = parents;
// Execute the macro to generate its node and children, and recursively execute them
this.child = this.executeMacro.call(this);
};
Macro.prototype.render = function(type) {
return this.child ? this.child.render(type) : "";
};
Macro.prototype.renderInDom = function(parentDomNode,insertBefore) {
if(this.child) {
this.child.renderInDom(parentDomNode,insertBefore);
this.postRenderInDom();
}
};
Macro.prototype.postRenderInDom = function() {
// Do nothing, individual macros can override
};
Macro.prototype.refresh = function(changes) {
var t,
self = this;
// Check if any of the dependencies of this macro node have changed
if(this.dependencies.hasChanged(changes,this.tiddlerTitle)) {
// Re-execute the macro if so
this.execute(this.parents,this.tiddlerTitle);
} else {
// Refresh the child node
if(this.child) {
this.child.refresh(changes);
}
}
};
/*
Macros that need special refreshing should override this function
*/
Macro.prototype.refreshInDom = function(changes) {
// Check if any of the dependencies of this macro node have changed
if(this.dependencies.hasChanged(changes,this.tiddlerTitle)) {
// Re-execute the macro if so
this.reexecuteInDom();
} else {
// Refresh any child
if(this.child) {
this.child.refreshInDom(changes);
}
}
};
/*
Re-execute a macro in the DOM
*/
Macro.prototype.reexecuteInDom = function() {
// Macros can only auto-refresh if one of their descendent child has a DOM node
var child = this.child;
while(!child.domNode && child.child) {
child = child.child;
}
var parentDomNode = child.domNode.parentNode,
insertBefore = child.domNode.nextSibling;
parentDomNode.removeChild(child.domNode);
this.execute(this.parents,this.tiddlerTitle);
this.renderInDom(parentDomNode,insertBefore);
};
Macro.prototype.addClass = function(className) {
this.classes = this.classes || [];
$tw.utils.pushTop(this.classes,className.split(" "));
};
exports.Macro = Macro;
})();

View File

@ -1,122 +0,0 @@
/*\
title: $:/core/modules/treenodes/node.js
type: application/javascript
module-type: treenode
Base class for all other tree nodes
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false, Node: false */
"use strict";
/*
The virtual base class for all types of renderer nodes. It keeps track of child nodes but otherwise contains no functionality
*/
var Node = function() {
if(this instanceof Node) {
} else {
return new Node();
}
};
/*
Makes a copy of a node, or returns the node itself if it doesn't need cloning because it doesn't have any state
*/
Node.prototype.clone = function() {
// By default we don't actually clone nodes, we just re-use them (we do clone macros and elements)
return this;
};
/*
Execute a node and derive its child nodes
parents: array of titles of each transcluded parent tiddler (used for detecting recursion)
tiddlerTitle: title of the context tiddler within which this node is being executed
*/
Node.prototype.execute = function(parents,tiddlerTitle) {
};
/*
Render a node and its children to a particular MIME type
type: Content type to which the node should be rendered
*/
Node.prototype.render = function(type) {
};
/*
Render a node and its children into the DOM
parentDomNode: node that should become the parent of the rendered node
insertBefore: optional node that the node should be inserted before
*/
Node.prototype.renderInDom = function(parentDomNode,insertBefore) {
};
/*
Re-execute a node if it is impacted by a set of tiddler changes
changes: hashmap of tiddler changes in the format used by $tw.Wiki
*/
Node.prototype.refresh = function(changes) {
};
/*
Re-execute a node if it is impacted by a set of tiddler changes, and update the associated DOM elements as necessary
changes: hashmap of tiddler changes in the format used by $tw.Wiki
*/
Node.prototype.refreshInDom = function(changes) {
};
/*
Add a class to the node
*/
Node.prototype.addClass = function(className) {
};
/*
Add styles to a node
*/
Node.prototype.addStyles = function(styles) {
};
/*
Given a tree node find the bounding rectange of its first child element
*/
Node.prototype.getNodeBounds = function() {
var t,bounds;
if(this.domNode) {
if(this.domNode.nodeType === 3) { // Node.TEXT_NODE
bounds = this.domNode.parentNode.getBoundingClientRect();
} else {
bounds = this.domNode.getBoundingClientRect();
}
// Absurdly, Firefox requires us to do this, otherwise JSON.stringify() gets confused
return {
top: bounds.top,
left: bounds.left,
right: bounds.right,
bottom: bounds.bottom,
width: bounds.width,
height: bounds.height
};
} else {
if(this.child) {
return this.child.getNodeBounds();
} else if(this.children) {
for(t=0; t<this.children.length; t++) {
bounds = this.children[t].getNodeBounds();
if(bounds) {
return bounds;
}
}
}
}
return null;
};
exports.Node = Node;
})();

View File

@ -1,40 +0,0 @@
/*\
title: $:/core/modules/treenodes/raw.js
type: application/javascript
module-type: treenode
Raw, unparsed HTML nodes
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Node = require("./node.js").Node;
var Raw = function(html) {
if(this instanceof Raw) {
this.html = html;
} else {
return new Raw(html);
}
};
Raw.prototype = new Node();
Raw.prototype.constructor = Raw;
Raw.prototype.render = function(type) {
return this.html;
};
Raw.prototype.renderInDom = function(domNode) {
this.domNode = document.createElement("div");
this.domNode.innerHTML = this.html;
domNode.appendChild(this.domNode);
};
exports.Raw = Raw;
})();

View File

@ -1,43 +0,0 @@
/*\
title: $:/core/modules/treenodes/text.js
type: application/javascript
module-type: treenode
Text nodes
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Node = require("./node.js").Node;
var Text = function(text) {
if(this instanceof Text) {
this.text = text;
} else {
return new Text(text);
}
};
Text.prototype = new Node();
Text.prototype.constructor = Text;
Text.prototype.render = function(type) {
return type === "text/html" ? $tw.utils.htmlEncode(this.text) : this.text;
};
Text.prototype.renderInDom = function(parentDomNode,insertBefore) {
this.domNode = document.createTextNode(this.text);
if(insertBefore) {
parentDomNode.insertBefore(this.domNode,insertBefore);
} else {
parentDomNode.appendChild(this.domNode);
}
};
exports.Text = Text;
})();

View File

@ -83,7 +83,7 @@ exports.getEmptyMessage = function() {
return {
type: "element",
tag: "span",
children: this.renderer.renderTree.wiki.new_parseText("text/vnd.tiddlywiki",this.emptyMessage).tree
children: this.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",this.emptyMessage).tree
};
};

View File

@ -73,7 +73,7 @@ exports.generateChildNodes = function() {
})) {
templateParseTree = [{type: "text", text: "Tiddler recursion error in transclude widget"}];
} else {
var parser = this.renderer.renderTree.wiki.new_parseTiddler(this.templateTitle,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
var parser = this.renderer.renderTree.wiki.parseTiddler(this.templateTitle,{parseAsInline: !this.renderer.parseTreeNode.isBlock});
templateParseTree = parser ? parser.tree : [];
}
}

View File

@ -21,7 +21,7 @@ var HtmlWikifiedViewer = function(viewWidget,tiddler,field,value) {
HtmlWikifiedViewer.prototype.render = function() {
// Parse the field text
var text = this.viewWidget.renderer.renderTree.wiki.new_renderText("text/html","text/vnd.tiddlywiki",this.value);
var text = this.viewWidget.renderer.renderTree.wiki.renderText("text/html","text/vnd.tiddlywiki",this.value);
// Create a node containing the HTML representation of the field
var node = {
type: "element",

View File

@ -32,7 +32,7 @@ WikifiedViewer.prototype.render = function() {
isBlock: this.viewWidget.renderer.parseTreeNode.isBlock
}];
} else {
parseTree = this.viewWidget.renderer.renderTree.wiki.new_parseText("text/vnd.tiddlywiki",this.value).tree;
parseTree = this.viewWidget.renderer.renderTree.wiki.parseText("text/vnd.tiddlywiki",this.value).tree;
}
return this.viewWidget.renderer.renderTree.createRenderers(this.viewWidget.renderer.renderContext,parseTree);
};

View File

@ -356,6 +356,19 @@ exports.clearCache = function(title) {
}
};
exports.initParsers = function(moduleType) {
// Install the new parser modules
$tw.wiki.newparsers = {};
var self = this;
$tw.modules.forEachModuleOfType("newparser",function(title,module) {
for(var f in module) {
if($tw.utils.hop(module,f)) {
$tw.wiki.newparsers[f] = module[f]; // Store the parser class
}
}
});
};
/*
Parse a block of text of a specified MIME type
type: content type of text to be parsed
@ -364,7 +377,7 @@ Parse a block of text of a specified MIME type
Options include:
parseAsInline: if true, the text of the tiddler will be parsed as an inline run
*/
exports.new_parseText = function(type,text,options) {
exports.parseText = function(type,text,options) {
options = options || {};
// Select a parser
var Parser = this.newparsers[type];
@ -387,13 +400,13 @@ exports.new_parseText = function(type,text,options) {
/*
Parse a tiddler according to its MIME type
*/
exports.new_parseTiddler = function(title,options) {
exports.parseTiddler = function(title,options) {
options = options || {};
var cacheType = options.parseAsInline ? "newInlineParseTree" : "newBlockParseTree",
tiddler = this.getTiddler(title),
self = this;
return tiddler ? this.getCacheForTiddler(title,cacheType,function() {
return self.new_parseText(tiddler.fields.type,tiddler.fields.text,options);
return self.parseText(tiddler.fields.type,tiddler.fields.text,options);
}) : null;
};
@ -403,8 +416,8 @@ Parse text in a specified format and render it into another format
textType: content type of the input text
text: input text
*/
exports.new_renderText = function(outputType,textType,text) {
var parser = this.new_parseText(textType,text),
exports.renderText = function(outputType,textType,text) {
var parser = this.parseText(textType,text),
renderTree = new $tw.WikiRenderTree(parser,{wiki: this});
renderTree.execute();
return renderTree.render(outputType);
@ -415,196 +428,13 @@ Parse text from a tiddler and render it into another format
outputType: content type for the output
title: title of the tiddler to be rendered
*/
exports.new_renderTiddler = function(outputType,title) {
var parser = this.new_parseTiddler(title),
exports.renderTiddler = function(outputType,title) {
var parser = this.parseTiddler(title),
renderTree = new $tw.WikiRenderTree(parser,{wiki: this});
renderTree.execute();
return renderTree.render(outputType);
};
exports.initParsers = function(moduleType) {
// Install the new parser modules
$tw.wiki.newparsers = {};
var self = this;
$tw.modules.forEachModuleOfType("newparser",function(title,module) {
for(var f in module) {
if($tw.utils.hop(module,f)) {
$tw.wiki.newparsers[f] = module[f]; // Store the parser class
}
}
});
// Install the parser modules
moduleType = moduleType || "parser";
$tw.wiki.parsers = {};
var self = this;
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
for(var f in module) {
if($tw.utils.hop(module,f)) {
$tw.wiki.parsers[f] = new module[f]({wiki: self}); // Store an instance of the parser
}
}
});
// Install the rules for the old wikitext parser rules
var wikitextparser = this.parsers["text/x-tiddlywiki"];
if(wikitextparser) {
wikitextparser.installRules();
}
};
/*
Parse a block of text of a specified MIME type
Options are:
defaultType: Default MIME type to use if the specified one is unknown
with: Optional array of strings to be substituted for $1, $2 etc.
*/
exports.parseText = function(type,text,options) {
options = options || {};
// Select a parser
var parser = this.parsers[type];
if(!parser && $tw.config.fileExtensionInfo[type]) {
parser = this.parsers[$tw.config.fileExtensionInfo[type].type];
}
if(!parser) {
parser = this.parsers[options.defaultType || "text/vnd.tiddlywiki"];
}
if(!parser) {
return null;
}
// Substitute any `with` tokens
if("with" in options) {
for(var token in options["with"]) {
var placeholderRegExp = new RegExp("\\$"+token,"mg");
text = text.replace(placeholderRegExp,options["with"][token]);
}
}
return parser.parse(type,text);
};
/*
Parse a tiddler according to its MIME type
Options are:
defaultType: Default MIME type to use if the specified one is unknown
with: Optional array of strings to be substituted for $1, $2 etc.
*/
exports.parseTiddler = function(title,options) {
options = options || {};
var me = this,
tiddler = this.getTiddler(title);
if("with" in options) {
return this.parseText(tiddler.fields.type,tiddler.fields.text,options);
} else {
return tiddler ? this.getCacheForTiddler(title,"parseTree",function() {
return me.parseText(tiddler.fields.type,tiddler.fields.text,options);
}) : null;
}
};
/*
Parse text in a specified format and render it into another format
outputType: content type for the output
textType: content type of the input text
text: input text
options: see wiki.parseText()
Options are:
defaultType: Default MIME type to use if the specified one is unknown
with: Optional array of strings to be substituted for $1, $2 etc.
*/
exports.renderText = function(outputType,textType,text,options) {
var renderer = this.parseText(textType,text,options);
renderer.execute([]);
return renderer.render(outputType);
};
/*
Parse text from a tiddler and render it into another format
outputType: content type for the output
title: title of the tiddler to be rendered
options: see wiki.parseText()
Options are:
defaultType: Default MIME type to use if the specified one is unknown
with: Optional array of strings to be substituted for $1, $2 etc.
*/
exports.renderTiddler = function(outputType,title,options) {
var renderer = this.parseTiddler(title,options);
renderer.execute([],title);
return renderer.render(outputType);
};
/*
Install macro modules into this wiki
moduleType: Module type to install (defaults to "macro")
It's useful to remember what the `new` keyword does. It:
# Creates a new object. It's type is a plain `object`
# Sets the new objects internal, inaccessible, `[[prototype]]` property to the
constructor function's external, accessible, `prototype` object
# Executes the constructor function, passing the new object as `this`
*/
exports.initMacros = function(moduleType) {
moduleType = moduleType || "macro";
$tw.wiki.macros = {};
var MacroClass = require("./treenodes/macro.js").Macro,
subclassMacro = function(module) {
// Make a copy of the Macro() constructor function
var MacroMaker = function Macro() {
MacroClass.apply(this,arguments);
};
// Set the prototype to a new instance of the prototype of the Macro class
MacroMaker.prototype = new MacroClass();
// Add the prototype methods for this instance of the macro
for(var f in module) {
if($tw.utils.hop(module,f)) {
MacroMaker.prototype[f] = module[f];
}
}
// Make a more convenient reference to the macro info
return MacroMaker;
};
$tw.modules.forEachModuleOfType(moduleType,function(title,module) {
$tw.wiki.macros[module.info.name] = subclassMacro(module);
});
};
/*
Install editor modules for the edit macro
*/
exports.initEditors = function(moduleType) {
moduleType = moduleType || "editor";
var editMacro = this.macros.edit;
if(editMacro) {
editMacro.editors = {};
$tw.modules.applyMethods(moduleType,editMacro.editors);
}
};
/*
Install field viewer modules for the view macro
*/
exports.initFieldViewers = function(moduleType) {
moduleType = moduleType || "fieldviewer";
var viewMacro = this.macros.view;
if(viewMacro) {
viewMacro.fieldviewers = {};
$tw.modules.applyMethods(moduleType,viewMacro.fieldviewers);
}
};
/*
Install list viewer modules for the list macro
*/
exports.initListViews = function(moduleType) {
moduleType = moduleType || "listview";
var listMacro = this.macros.list;
if(listMacro) {
listMacro.listviews = {};
$tw.modules.applyMethods(moduleType,listMacro.listviews);
}
};
/*
Select the appropriate saver modules and set them up
*/

View File

@ -1,7 +1,6 @@
title: $:/templates/EditTemplate
modifier: JeremyRuston
<div class="tw-tiddler-frame">
<<view title>> <<button SaveTiddler class:"btn btn-mini btn-success"><done>>
{{title{

View File

@ -1,68 +0,0 @@
title: $:/templates/NewPageTemplate
\define coolmacro(p:ridiculously) This is my $p$ cool macro!
\define me(one two)
some<br>thing
New paragraph
\end
\define another(first:default second third:default3) that is
@@.something
@@background-color:green;
* This
*.disabled Is a
* List!!
An inline {{{ [tag[docs]tag[introduction]sort[title]] }}}.anotherClassy yes it is!
<<me red green>>
Inline macro call: <<me red green>>
|table|k
| this | is | a | table |
| yes | indeed |>| it is |
{{Acknowledgements|with a tooltip||$:/templates/NewViewTemplate}width:40;height:50;background-color:red;}.one
And this is an inline transclusion {{Acknowledgements}width:40;height:50;}.one
---
```
Some monospaced
```
This is a @@.myClass normal@@ para and @@background-color:red; one@@ `with` so<!--and a comment-->me `code` blocks -- and both kinds of dashes --- just for the fun of it. And ''some bold'' text and //italics//, ^^superscript^^ and ,,subscript,, and even some __underlined text__. Oh a ~~strikethrough~~.
some text ~~strike start -- ndash --- mdash strike end~~ -> nok
@@
<!--This is another comment-->
<_navigator story="$:/StoryList" history="$:/HistoryList">
<_link to="JeremyRuston" hover="HelloThere">
Go to it!
</_link>
! Heading1
!!.myclass Heading2
!!! Heading3
!!!! Heading4
<div class="container">
<div class="row">
<div class="span10">
<_list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/templates/NewViewTemplate" editTemplate="$:/templates/EditTemplate" listview=classic itemClass="tw-tiddler-frame"/>
</div>
</div>
</div>
</_navigator>

View File

@ -1,7 +0,0 @@
title: $:/templates/NewStaticContent
type: text/vnd.tiddlywiki
<!-- For Google, and people without JavaScript-->
<_list filter="[!is[shadow]sort[title]]" >
<_view field="title" format="text"></_view>
</_list>

View File

@ -1,17 +0,0 @@
title: $:/templates/NewViewTemplate
modifier: JeremyRuston
<span class="title">
<_view field="title"/>
<_button message="tw-close">close</_button>
</span>
<div class="small">
<_view field="modifier" format="link"/>
<_view field="modified" format="date"/>
</div>
<div class="body">
<_view field="text" format="wikified">
</_view>
</div>

View File

@ -1,87 +1,37 @@
title: $:/templates/PageTemplate
<!-- The navigator catches navigation events and updates the story and history tiddlers -->
<<navigator story:"$:/StoryList" history:"$:/HistoryList"><
<_navigator story="$:/StoryList" history="$:/HistoryList">
<!-- The top navigation bar -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
{{nav{
<!-- Navigation menu -->
@@.nav
* HelloThere
* [[Docs]]
*.divider-vertical
<!-- Search box -->
<form class="form-search">
{{search-query{
<<edit tiddler:[[$:/temp/search]] type:search requireFocus:yes>>
}}}
<div style="position:absolute; z-index:1000;">
<<reveal state:[[$:/temp/search]] type:nomatch text:""><
<div class="open">
{{dropdown-menu{
* <<list filter:"[!is[shadow]searchVia[$:/temp/search]sort[title]limit[50]]" template:"$:/templates/SearchResultTemplate" emptyMessage:"//No results//">>
}}}
</div>
>>
</div>
</form>
<!-- Full screen button -->
<<button full-screen class:"btn btn-warning"><Full screen>>
<!-- Edit button dropdown -->
{{pull-right{
<<reveal state:[[$:/EditMode]] type:nomatch text:yes><
<<button modal param:[[$:/messages/EnterEditMode]] set:[[$:/EditMode]] setTo:yes class:"btn btn-success"><Edit>>
>>
<!-- These buttons are only visible in edit mode -->
<<reveal state:[[$:/EditMode]] type:match text:yes><
<!-- New tiddler button -->
<<button NewTiddler class:"btn btn-success"><New>>
<!-- Save buttons -->
<<button save-wiki param:"$:/core/templates/tiddlywiki5.encrypted.template.html" class:"btn pull-right"><Save Changes (encrypted)>>
<<button save-wiki class:"btn pull-right"><Save Changes>>
>>
}}}
}}}
@@
</div>
</div>
</div>
<!-- The main story references the same story and history tiddlers as the outer navigator -->
<!-- The main display container -->
<div class="container">
<div class="row">
<div class="span2">
<div style="position:fixed;">
<<scrollable width:"104px"><
<<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" listview:classic itemClass:"tw-menu-list-item">>
>>
<!-- The navigation menu -->
<_list filter="[list[$:/StoryList]]" history="$:/HistoryList" editTemplate="$:/templates/EditTemplate" listview=classic itemClass="tw-menu-list-item"/>
</div>
</div>
<div class="span10">
<<list filter:"[list[$:/StoryList]]" history:"$:/HistoryList" template:"$:/templates/ViewTemplate" editTemplate:"$:/templates/EditTemplate" listview:classic itemClass:"tw-tiddler-frame">>
<!-- The main display -->
<_list filter="[list[$:/StoryList]]" history="$:/HistoryList" template="$:/templates/ViewTemplate" editTemplate="$:/templates/EditTemplate" listview=classic itemClass="tw-tiddler-frame"/>
</div>
</div>
</div>
>>
</_navigator>

View File

@ -1,9 +1,7 @@
title: $:/templates/StaticContent
type: text/vnd.tiddlywiki
<<! For Google, and people without JavaScript >>
<<list filter:[!is[shadow]sort[title]]><
<div><<view title text>></div>
>>
<!-- For Google, and people without JavaScript-->
<_list filter="[!is[shadow]sort[title]]" >
<_view field="title" format="text"></_view>
</_list>

View File

@ -1,31 +1,17 @@
title: $:/templates/ViewTemplate
modifier: JeremyRuston
<<button popup:"$:/temp/FieldsDropDownLocation" qualifyTiddlerTitles:yes class:"btn-invisible"><
<span class="title"><<view title>> </span>
>>
<span> <<reveal state:[[$:/EditMode]] type:match text:yes>< <<button EditTiddler class:"btn-invisible"><[img[$:/core/images/edit-button.svg]]>> >> </span>
<<button close class:"btn-invisible pull-right"><[img[$:/core/images/close-button.svg]]>>
<div class:"small"><<view modifier link>> <<view modified relativedate>></div>
<<reveal state:"$:/temp/FieldsDropDownLocation" type:popup qualifyTiddlerTitles:yes><
<div class="open">
{{dropdown-menu table table-condensed table-bordered{
<<fields>>
}}}
<span class="title">
<_view field="title"/>
<_button message="tw-close">close</_button>
</span>
<div class="small">
<_view field="modifier" format="link"/>
<_view field="modified" format="date"/>
</div>
>>
{{tw-tags-wrapper{
<<list filter:[is[current]tags[]] template:"$:/templates/TagTemplate" block:no>>
}}}
<div class="body">
<<view text wikified>>
<_view field="text" format="wikified">
</_view>
</div>

View File

@ -1,58 +0,0 @@
title: $:/core/templates/new.tiddlywiki5.template.html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="{{version}}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="format-detection" content="telephone=no">
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
<title>{{$:/core/wiki/title}}</title>
<!----------- This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ----------->
<!----------- Raw markup ----------->
{{{ [tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
</head>
<body>
<!----------- Static styles ----------->
<div id="styleArea">
{{{ [is[shadow]type[text/css]] ||$:/core/templates/css-tiddler}}}
</div>
<!----------- Static content for Google and browsers without JavaScript ----------->
<noscript>
<div id="splashArea">
{{$:/templates/NewStaticContent||$:/core/templates/html-tiddler}}
</div>
</noscript>
<!----------- Miscellaneous shadow tiddlers ----------->
<div id="shadowArea" style="display:none;">
{{{ [is[shadow]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/core/boot.js]] -[[$:/core/bootprefix.js]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Ordinary tiddlers ----------->
<div id="storeArea" style="display:none;">
{{{ [!is[shadow]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Library modules ----------->
<div id="libraryModules" style="display:none;">
{{$:/core/lib/jquery.min.js||$:/core/templates/javascript-tiddler}}
{{{ [is[shadow]type[application/javascript]library[yes]] -[[$:/core/lib/jquery.min.js]] ||$:/core/templates/javascript-tiddler}}}
</div>
<!----------- Boot kernel prologue ----------->
<div id="bootKernelPrefix" style="display:none;">
{{ $:/core/bootprefix.js ||$:/core/templates/javascript-tiddler}}
</div>
<!----------- Plugin modules ----------->
<div id="modules" style="display:none;">
{{{ [is[shadow]type[application/javascript]has[module-type]] ||$:/core/templates/module-tiddler}}}
</div>
<!----------- Boot kernel ----------->
<div id="bootKernel" style="display:none;">
{{ $:/core/boot.js ||$:/core/templates/javascript-tiddler}}
</div>
</body>
</html>

View File

@ -1,23 +1,21 @@
title: $:/core/templates/static.template.html
type: text/vnd.tiddlywiki-html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="<<serialize "$:/core/version.txt" text/plain>>" />
<meta name="tiddlywiki-version" content="{{version}}" />
<meta name="format-detection" content="telephone=no">
<meta name="copyright" content="
<<serialize "$:/core/copyright.txt" text/plain>>
" />
<title><<tiddler target:$:/shadows/title>></title>
<!----------- This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ----------->
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
<title>{{$:/core/wiki/title}}</title>
<div id="styleArea">
<<serialize "[type[text/css]]" application/x-tiddler-css>>
{{{ [is[shadow]type[text/css]] ||$:/core/templates/css-tiddler}}}
</div>
</head>
<body>
<<serialize "$:/templates/PageTemplate" text/html>>
{{$:/templates/PageTemplate||$:/core/templates/html-tiddler}}
</body>
</html>

View File

@ -1,57 +1,58 @@
title: $:/core/templates/tiddlywiki5.encrypted.template.html
type: text/vnd.tiddlywiki-html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="<<version>>" />
<meta name="tiddlywiki-version" content="{{version}}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="format-detection" content="telephone=no">
<meta name="copyright" content="
<<serialize "$:/core/copyright.txt" text/plain>>
" />
<title><<tiddler "$:/core/wiki/title">></title>
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
<title>{{$:/core/wiki/title}}</title>
<!----------- This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ----------->
<!----------- Raw markup ----------->
<<serialize "[tag[$:/core/wiki/rawmarkup]]" text/plain>>
{{{ [tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
</head>
<body>
<!----------- Static styles ----------->
<div id="styleArea">
<<serialize "[is[shadow]type[text/css]]" application/x-tiddler-css>>
{{{ [is[shadow]type[text/css]] ||$:/core/templates/css-tiddler}}}
</div>
<!----------- Static content for Google and browsers without JavaScript ----------->
<noscript>
<div id="splashArea">
<<serialize "$:/templates/StaticContent" text/html>>
{{$:/templates/NewStaticContent||$:/core/templates/html-tiddler}}
</div>
</noscript>
<!----------- Encrypted tiddlers ----------->
<div id="encryptedArea" style="display:none;">
<<serialize "[is[shadow]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/core/boot.js]] -[[$:/core/bootprefix.js]]" application/x-tiddler-encrypted-div>>
<<serialize "[!is[shadow]]" application/x-tiddler-encrypted-div>>
<!----------- Miscellaneous shadow tiddlers ----------->
<div id="shadowArea" style="display:none;">
{{{ [is[shadow]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/core/boot.js]] -[[$:/core/bootprefix.js]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Ordinary tiddlers ----------->
<div id="storeArea" style="display:none;">
{{{ [!is[shadow]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Library modules ----------->
<div id="libraryModules" style="display:none;">
<<serialize "[[$:/core/lib/jquery.min.js]]" application/x-tiddler-library>>
<<serialize "[is[shadow]type[application/javascript]library[yes]] -[[$:/core/lib/jquery.min.js]]" application/x-tiddler-library>>
{{$:/core/lib/jquery.min.js||$:/core/templates/javascript-tiddler}}
{{{ [is[shadow]type[application/javascript]library[yes]] -[[$:/core/lib/jquery.min.js]] ||$:/core/templates/javascript-tiddler}}}
</div>
<!----------- Boot kernel prologue ----------->
<div id="bootKernelPrefix" style="display:none;">
<<serialize "$:/core/bootprefix.js" application/javascript>>
{{ $:/core/bootprefix.js ||$:/core/templates/javascript-tiddler}}
</div>
<!----------- Plugin modules ----------->
<div id="modules" style="display:none;">
<<serialize "[is[shadow]type[application/javascript]has[module-type]]" application/x-tiddler-module>>
{{{ [is[shadow]type[application/javascript]has[module-type]] ||$:/core/templates/module-tiddler}}}
</div>
<!----------- Boot kernel ----------->
<div id="bootKernel" style="display:none;">
<<serialize "$:/core/boot.js" application/javascript>>
{{ $:/core/boot.js ||$:/core/templates/javascript-tiddler}}
</div>
</body>
</html>

View File

@ -1,60 +1,58 @@
title: $:/core/templates/tiddlywiki5.template.html
type: text/vnd.tiddlywiki-html
\rules only filteredtranscludeinline transcludeinline
<!doctype html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="application-name" content="TiddlyWiki" />
<meta name="generator" content="TiddlyWiki" />
<meta name="tiddlywiki-version" content="<<version>>" />
<meta name="tiddlywiki-version" content="{{version}}" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="format-detection" content="telephone=no">
<meta name="copyright" content="
<<serialize "$:/core/copyright.txt" text/plain>>
" />
<title><<tiddler "$:/core/wiki/title">></title>
<meta name="copyright" content="{{$:/core/copyright.txt}}" />
<title>{{$:/core/wiki/title}}</title>
<!----------- This is a Tiddlywiki file. The points of interest in the file are marked with this pattern ----------->
<!----------- Raw markup ----------->
<<serialize "[tag[$:/core/wiki/rawmarkup]]" text/plain>>
{{{ [tag[$:/core/wiki/rawmarkup]] ||$:/core/templates/plain-text-tiddler}}}
</head>
<body>
<!----------- Static styles ----------->
<div id="styleArea">
<<serialize "[is[shadow]type[text/css]]" application/x-tiddler-css>>
{{{ [is[shadow]type[text/css]] ||$:/core/templates/css-tiddler}}}
</div>
<!----------- Static content for Google and browsers without JavaScript ----------->
<noscript>
<div id="splashArea">
<<serialize "$:/templates/StaticContent" text/html>>
{{$:/templates/NewStaticContent||$:/core/templates/html-tiddler}}
</div>
</noscript>
<!----------- Miscellaneous shadow tiddlers ----------->
<div id="shadowArea" style="display:none;">
<<serialize "[is[shadow]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/core/boot.js]] -[[$:/core/bootprefix.js]]" application/x-tiddler-html-div>>
{{{ [is[shadow]] -[type[text/css]] -[type[application/javascript]has[module-type]] -[type[application/javascript]library[yes]] -[[$:/core/boot.js]] -[[$:/core/bootprefix.js]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Ordinary tiddlers ----------->
<div id="storeArea" style="display:none;">
<<serialize "[!is[shadow]]" application/x-tiddler-html-div>>
{{{ [!is[shadow]] ||$:/core/templates/html-div-tiddler}}}
</div>
<!----------- Library modules ----------->
<div id="libraryModules" style="display:none;">
<<serialize "[[$:/core/lib/jquery.min.js]]" application/x-tiddler-library>>
<<serialize "[is[shadow]type[application/javascript]library[yes]] -[[$:/core/lib/jquery.min.js]]" application/x-tiddler-library>>
{{$:/core/lib/jquery.min.js||$:/core/templates/javascript-tiddler}}
{{{ [is[shadow]type[application/javascript]library[yes]] -[[$:/core/lib/jquery.min.js]] ||$:/core/templates/javascript-tiddler}}}
</div>
<!----------- Boot kernel prologue ----------->
<div id="bootKernelPrefix" style="display:none;">
<<serialize "$:/core/bootprefix.js" application/javascript>>
{{ $:/core/bootprefix.js ||$:/core/templates/javascript-tiddler}}
</div>
<!----------- Plugin modules ----------->
<div id="modules" style="display:none;">
<<serialize "[is[shadow]type[application/javascript]has[module-type]]" application/x-tiddler-module>>
{{{ [is[shadow]type[application/javascript]has[module-type]] ||$:/core/templates/module-tiddler}}}
</div>
<!----------- Boot kernel ----------->
<div id="bootKernel" style="display:none;">
<<serialize "$:/core/boot.js" application/javascript>>
{{ $:/core/boot.js ||$:/core/templates/javascript-tiddler}}
</div>
</body>
</html>

View File

@ -8,6 +8,8 @@ Welcome to TiddlyWiki5, a reboot of TiddlyWiki, the reusable non-linear personal
TiddlyWiki is designed to fit around your brain, giving you a better way of managing information compared to traditional documents and emails. The fundamental idea is that information is more useful and reusable if we cut it up into the smallest semantically meaningful chunks -- [[tiddlers|Tiddlers]] -- and give them titles so that they can be structured with links, tags and macros. TiddlyWiki aims to provide a fluid interface for working with tiddlers, allowing them to be aggregated and composed into longer narratives.
//''28th December 2012'' - the TiddlyWiki5 core code is in the midst of some major refactoring upheavals, and there have been several regressions that will be fixed over the next few days, along with bringing the documentation back up to date//
TiddlyWiki5 has many [[improvements|Improvements]] over the original. It is currently labelled alpha, meaning it is working but incomplete. It is the best possible time to get involved and support its future development. You can:
* Explore its features online at http://five.tiddlywiki.com/

1
node_modules/.bin/esparse generated vendored
View File

@ -1 +0,0 @@
../esprima/bin/esparse.js

5
node_modules/esprima/.travis.yml generated vendored
View File

@ -1,5 +0,0 @@
language: node_js
node_js:
- 0.4
- 0.6

19
node_modules/esprima/LICENSE.BSD generated vendored
View File

@ -1,19 +0,0 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Some files were not shown because too many files have changed in this diff Show More