mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-23 10:07:19 +00:00
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:
parent
d6e531e87c
commit
b006cf163f
1
bld.sh
1
bld.sh
@ -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 \
|
||||
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
})();
|
@ -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
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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();
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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)];
|
||||
};
|
||||
|
||||
})();
|
@ -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)])];
|
||||
};
|
||||
|
||||
})();
|
@ -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)])];
|
||||
};
|
||||
|
||||
})();
|
@ -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();
|
||||
};
|
||||
|
||||
})();
|
@ -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 ? "–" : "—";
|
||||
return [$tw.Tree.Entity(dash)];
|
||||
};
|
||||
|
||||
})();
|
@ -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)];
|
||||
};
|
||||
|
||||
})();
|
@ -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: ©
|
||||
}}}
|
||||
|
||||
\*/
|
||||
(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])];
|
||||
};
|
||||
|
||||
})();
|
@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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)];
|
||||
};
|
||||
|
||||
})();
|
@ -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];
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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 [];
|
||||
};
|
||||
|
||||
})();
|
@ -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]];
|
||||
};
|
||||
|
||||
})();
|
@ -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 [];
|
||||
};
|
||||
|
||||
})();
|
@ -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 [];
|
||||
};
|
||||
|
||||
})();
|
@ -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",{},[])];
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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];
|
||||
};
|
||||
|
||||
})();
|
@ -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 [];
|
||||
};
|
||||
|
||||
})();
|
@ -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 [];
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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];
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
35
core/modules/parsers/wikiparser/rules/commentblock.js
Normal file
35
core/modules/parsers/wikiparser/rules/commentblock.js
Normal 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 [];
|
||||
};
|
||||
|
||||
})();
|
@ -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) {
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
})();
|
@ -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);
|
||||
|
@ -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";
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
})();
|
@ -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 = {};
|
||||
|
||||
})();
|
@ -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)
|
||||
]);
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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;
|
||||
|
||||
})();
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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 : [];
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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{
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
1
node_modules/.bin/esparse
generated
vendored
@ -1 +0,0 @@
|
||||
../esprima/bin/esparse.js
|
5
node_modules/esprima/.travis.yml
generated
vendored
5
node_modules/esprima/.travis.yml
generated
vendored
@ -1,5 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
||||
|
19
node_modules/esprima/LICENSE.BSD
generated
vendored
19
node_modules/esprima/LICENSE.BSD
generated
vendored
@ -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
Loading…
Reference in New Issue
Block a user