add s3ajax libaries

This commit is contained in:
Kenneth Reitz
2007-05-10 22:29:43 +00:00
parent c10d97a9b3
commit af89410d2c
12 changed files with 2748 additions and 0 deletions
+428
View File
@@ -0,0 +1,428 @@
/**
S3Ajax v0.1 - An AJAX wrapper package for Amazon S3
http://decafbad.com/trac/wiki/S3Ajax
l.m.orchard@pobox.com
Share and Enjoy.
Requires:
http://pajhome.org.uk/crypt/md5/sha1.js
*/
// TODO: Figure out if Safari doesn't support PUT and DELETE
S3Ajax = {
// Defeat caching with query params on GET requests?
DEFEAT_CACHE: false,
// Default ACL to use when uploading keys.
DEFAULT_ACL: 'public-read',
// Default content-type to use in uploading keys.
DEFAULT_CONTENT_TYPE: 'text/plain',
/**
DANGER WILL ROBINSON - Do NOT fill in your KEY_ID and SECRET_KEY
here. These should be supplied by client-side code, and not
stored in any server-side files. Failure to protect your S3
credentials will result in surly people doing nasty things
on your tab.
For example, scoop values up from un-submitted form fields like so:
S3Ajax.KEY_ID = $('key_id').value;
S3Ajax.SECRET_KEY = $('secret_key').value;
*/
URL: 'http://s3.amazonaws.com',
KEY_ID: '',
SECRET_KEY: '',
// Flip this to true to potentially get lots of wonky logging.
DEBUG: false,
/**
Get contents of a key in a bucket.
*/
get: function(bucket, key, cb, err_cb) {
return this.httpClient({
method: 'GET',
resource: '/' + bucket + '/' + key,
load: function(req, obj) {
if (cb) return cb(req, req.responseText);
},
error: function(req, obj) {
if (err_cb) return err_cb(req, obj);
if (cb) return cb(req, req.responseText);
}
})
},
/**
Head the meta of a key in a bucket.
*/
head: function(bucket, key, cb, err_cb) {
return this.httpClient({
method: 'HEAD',
resource: '/' + bucket + '/' + key,
load: function(req, obj) {
if (cb) return cb(req, req.responseText);
},
error: function(req, obj) {
if (err_cb) return err_cb(req, obj);
if (cb) return cb(req, req.responseText);
}
})
},
/**
Put data into a key in a bucket.
*/
put: function(bucket, key, content/*, [params], cb, [err_cb]*/) {
// Process variable arguments for optional params.
var idx = 3;
var params = {};
if (typeof arguments[idx] == 'object')
params = arguments[idx++];
var cb = arguments[idx++];
var err_cb = arguments[idx++];
if (!params.content_type)
params.content_type = this.DEFAULT_CONTENT_TYPE;
if (!params.acl)
params.acl = this.DEFAULT_ACL;
return this.httpClient({
method: 'PUT',
resource: '/' + bucket + '/' + key,
content: content,
content_type: params.content_type,
meta: params.meta,
acl: params.acl,
load: function(req, obj) {
if (cb) return cb(req);
},
error: function(req, obj) {
if (err_cb) return err_cb(req, obj);
if (cb) return cb(req, obj);
}
});
},
/**
List buckets belonging to the account.
*/
listBuckets: function(cb, err_cb) {
return this.httpClient({
method:'GET', resource:'/',
force_lists: [ 'ListAllMyBucketsResult.Buckets.Bucket' ],
load: cb, error:err_cb
});
},
/**
Create a new bucket for this account.
*/
createBucket: function(bucket, cb, err_cb) {
return this.httpClient({
method:'PUT', resource:'/'+bucket, load:cb, error:err_cb
});
},
/**
Delete an empty bucket.
*/
deleteBucket: function(bucket, cb, err_cb) {
return this.httpClient({
method:'DELETE', resource:'/'+bucket, load:cb, error:err_cb
});
},
/**
Given a bucket name and parameters, list keys in the bucket.
*/
listKeys: function(bucket, params, cb, err_cb) {
return this.httpClient({
method:'GET', resource: '/'+bucket,
force_lists: [ 'ListBucketResult.Contents' ],
params:params, load:cb, error:err_cb
});
},
/**
Delete a single key in a bucket.
*/
deleteKey: function(bucket, key, cb, err_cb) {
return this.httpClient({
method:'DELETE', resource: '/'+bucket+'/'+key, load:cb, error:err_cb
});
},
/**
Delete a list of keys in a bucket, with optional callbacks
for each deleted key and when list deletion is complete.
*/
deleteKeys: function(bucket, list, one_cb, all_cb) {
var _this = this;
// If the list is empty, then fire off the callback.
if (!list.length && all_cb) return all_cb();
// Fire off key deletion with a callback to delete the
// next part of list.
var key = list.shift();
this.deleteKey(bucket, key, function() {
if (one_cb) one_cb(key);
_this.deleteKeys(bucket, list, one_cb, all_cb);
});
},
/**
Perform an authenticated S3 HTTP query.
*/
httpClient: function(kwArgs) {
var _this = this;
// If need to defeat cache, toss in a date param on GET.
if (this.DEFEAT_CACHE && ( kwArgs.method == "GET" || kwArgs.method == "HEAD" ) ) {
if (!kwArgs.params) kwArgs.params = {};
kwArgs.params["___"] = new Date().getTime();
}
// Prepare the query string and URL for this request.
var qs = (kwArgs.params) ? '?'+queryString(kwArgs.params) : '';
var url = this.URL + kwArgs.resource + qs;
var hdrs = {};
// Handle Content-Type header
if (!kwArgs.content_type && kwArgs.method == 'PUT')
kwArgs.content_type = 'text/plain';
if (kwArgs.content_type)
hdrs['Content-Type'] = kwArgs.content_type;
else
kwArgs.content_type = '';
// Set the timestamp for this request.
var http_date = this.httpDate();
hdrs['Date'] = http_date;
var content_MD5 = '';
/*
// TODO: Fix this Content-MD5 stuff.
if (kwArgs.content && kwArgs.content.hashMD5) {
content_MD5 = kwArgs.content.hashMD5();
hdrs['Content-MD5'] = content_MD5;
}
*/
// Handle the ACL parameter
var acl_header_to_sign = '';
if (kwArgs.acl) {
hdrs['x-amz-acl'] = kwArgs.acl;
acl_header_to_sign = "x-amz-acl:"+kwArgs.acl+"\n";
}
// Handle the metadata headers
var meta_to_sign = '';
if (kwArgs.meta) {
for (var k in kwArgs.meta) {
hdrs['x-amz-meta-'+k] = kwArgs.meta[k];
meta_to_sign += "x-amz-meta-"+k+":"+kwArgs.meta[k]+"\n";
}
}
// Only perform authentication if non-anonymous and credentials available
if (kwArgs['anonymous'] != true && this.KEY_ID && this.SECRET_KEY) {
// Build the string to sign for authentication.
var s;
s = kwArgs.method + "\n";
s += content_MD5 + "\n";
s += kwArgs.content_type + "\n";
s += http_date + "\n";
s += acl_header_to_sign;
s += meta_to_sign;
s += kwArgs.resource;
// Sign the string with our SECRET_KEY.
var signature = this.hmacSHA1(s, this.SECRET_KEY);
hdrs['Authorization'] = "AWS "+this.KEY_ID+":"+signature;
}
// Perform the HTTP request.
var req = getXMLHttpRequest();alert('test');
req.open(kwArgs.method, url, true);
for (var k in hdrs) req.setRequestHeader(k, hdrs[k]);
req.onreadystatechange = function() {
if (req.readyState == 4) {
// Pre-digest the XML if needed.
var obj = null;
if (req.responseXML && kwArgs.parseXML != false)
obj = _this.xmlToObj(req.responseXML, kwArgs.force_lists);
// Stash away the last request details, if DEBUG active.
if (_this.DEBUG) {
window._lastreq = req;
window._lastobj = obj;
}
// Dispatch to appropriate handler callback
if ( (req.status >= 400 || (obj && obj.Error) ) && kwArgs.error)
return kwArgs.error(req, obj);
else
return kwArgs.load(req, obj);
}
}
req.send(kwArgs.content);
return req;
},
/**
Turn a simple structure of nested XML elements into a
JavaScript object.
TODO: Handle attributes?
*/
xmlToObj: function(parent, force_lists, path) {
var obj = {};
var cdata = '';
var is_struct = false;
for(var i=0,node; node=parent.childNodes[i]; i++) {
if (3 == node.nodeType) {
cdata += node.nodeValue;
} else {
is_struct = true;
var name = node.nodeName;
var cpath = (path) ? path+'.'+name : name;
var val = arguments.callee(node, force_lists, cpath);
if (!obj[name]) {
var do_force_list = false;
if (force_lists) {
for (var j=0,item; item=force_lists[j]; j++) {
if (item == cpath) {
do_force_list=true; break;
}
}
}
obj[name] = (do_force_list) ? [ val ] : val;
} else if (obj[name].length) {
// This is a list of values to append this one to the end.
obj[name].push(val);
} else {
// Has been a single value up till now, so convert to list.
obj[name] = [ obj[name], val ];
}
}
}
// If any subnodes were found, return a struct - else return cdata.
return (is_struct) ? obj : cdata;
},
/**
Abstract HMAC SHA1 signature calculation.
*/
hmacSHA1: function(data, secret) {
// TODO: Alternate Dojo implementation?
return b64_hmac_sha1(secret, data)+'=';
},
/**
Return a date formatted appropriately for HTTP Date header.
Inspired by: http://www.svendtofte.com/code/date_format/
TODO: Should some/all of this go into common.js?
*/
httpDate: function(d) {
// Use now as default date/time.
if (!d) d = new Date();
// Date abbreviations.
var daysShort = ["Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"];
var monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// See: http://www.quirksmode.org/js/introdate.html#sol
function takeYear(theDate) {
var x = theDate.getYear();
var y = x % 100;
y += (y < 38) ? 2000 : 1900;
return y;
};
// Number padding function
function zeropad(num, sz) {
return ( (sz - (""+num).length) > 0 ) ?
arguments.callee("0"+num, sz) : num;
};
function gmtTZ(d) {
// Difference to Greenwich time (GMT) in hours
var os = Math.abs(d.getTimezoneOffset());
var h = ""+Math.floor(os/60);
var m = ""+(os%60);
h.length == 1? h = "0"+h:1;
m.length == 1? m = "0"+m:1;
return d.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
};
var s;
s = daysShort[d.getDay()] + ", ";
s += d.getDate() + " ";
s += monthsShort[d.getMonth()] + " ";
s += takeYear(d) + " ";
s += zeropad(d.getHours(), 2) + ":";
s += zeropad(d.getMinutes(), 2) + ":";
s += zeropad(d.getSeconds(), 2) + " ";
s += gmtTZ(d);
return s;
},
/* Help protect against errant end-commas */
EOF: null
};
if (!window['queryString']) {
// Swiped from MochiKit
function queryString(params) {
var l = [];
for (k in params)
l.push(k+'='+encodeURIComponent(params[k]))
return l.join("&");
}
}
if (!window['getXMLHttpRequest']) {
// Shamelessly swiped from MochiKit/Async.js
function getXMLHttpRequest() {
var self = arguments.callee;
if (!self.XMLHttpRequest) {
var tryThese = [
function () { return new XMLHttpRequest(); },
function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
function () { return null; }
];
for (var i = 0; i < tryThese.length; i++) {
var func = tryThese[i];
try {
self.XMLHttpRequest = func;
return func();
} catch (e) {
// pass
}
}
}
return self.XMLHttpRequest();
}
}
+156
View File
@@ -0,0 +1,156 @@
/**
Common can't-live-without stuff from MochiKit, Dojo, etal.
Share and Enjoy
*/
if (!window.Node) {
window.Node = {
ELEMENT_NODE : 1,
ATTRIBUTE_NODE : 2,
TEXT_NODE : 3,
CDATA_SECTION_NODE : 4,
ENTITY_REFERENCE_NODE : 5,
ENTITY_NODE : 6,
PROCESSING_INSTRUCTIONS_NODE : 7,
COMMENT_NODE : 8,
DOCUMENT_NODE : 9,
DOCUMENT_TYPE_NODE : 10,
DOCUMENT_FRAGMENT_NODE : 11,
NOTATION_NODE : 12
}
}
if (!window['addLoadEvent']) {
// See: http://simon.incutio.com/archive/2004/05/26/addLoadEvent
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
}
if (!window['$']) {
// Swiped from MochiKit / Prototype
function $(id) { return document.getElementById(id); }
}
/**
Get the parsed XML response from an HTTP request, even if
the server claimed a non-XML mimetype.
*/
function getResponseXML(rv) {
if (rv.responseXML) return rv.responseXML;
else return loadXML(rv.responseText);
}
function loadXML(data) {
if (DOMParser) return (new DOMParser()).parseFromString(data, 'text/xml');
if (ActiveXObject) return (new ActiveXObject("microsoft.XMLDOM")).loadXML(data);
return null;
}
function clearList(lid) {
$(lid).options.length = 0;
}
function addToList(lid, label, key) {
var list = $(lid);
list.options[list.options.length] = new Option(label, key);
}
function setList(lid, items) {
var list = $(lid);
this.clearList(lid);
for(i=0;i<items.length;i+=2) {
list.options[i/2] = new Option(items[i],items[i+1]);
}
}
function getSelected(lid) {
var sel = [];
var options = $(lid).options;
for (var i=0, item; item=options[i]; i++) {
if (item.selected) sel.push(item.value);
}
return sel;
}
/*
Mini MochiKit
*/
function forEach(list, fn) {
for (var i=0; i<list.length; i++) fn(list[i]);
}
function filter(fn, list) {
var rv = [];
for (var i=0; i<list.length; i++)
if (fn(list[i]))
rv[rv.length] = list[i];
return rv;
}
function map(fn, list) {
var rv = [];
for (var i=0; i<list.length; i++) rv[rv.length] = fn(list[i]);
return rv;
}
function appendChildNodes(parent, nodes) {
for (var i=0; i<nodes.length; i++) {
var node = nodes[i];
if (node.nodeType)
parent.appendChild(node);
else if ( (typeof(node) == 'object') && node.length)
appendChildNodes(parent, node);
else
parent.appendChild(document.createTextNode(''+node));
}
}
function createDOM(name, attrs, nodes) {
var elem = document.createElement(name);
if (attrs) for (k in attrs) {
var v = attrs[k];
if (k.substring(0, 2) == "on") {
if (typeof(v) == "string") {
v = new Function(v);
}
elem[k] = v;
} else {
elem.setAttribute(k, v);
}
switch(k) {
// MSIE seems to want this.
case 'class': elem.className = v; break;
}
}
if (nodes) appendChildNodes(elem, nodes);
return elem;
}
function createDOMFunc(name) {
return function(attrs) {
var nodes = [];
for (var i=1; i<arguments.length; i++)
nodes[nodes.length] = arguments[i];
return createDOM(name, attrs, nodes);
}
}
forEach([
'A', 'BUTTON', 'BR', 'CANVAS', 'DIV', 'FIELDSET', 'FORM',
'H1', 'H2', 'H3', 'HR', 'IMG', 'INPUT', 'LABEL', 'LEGEND', 'LI', 'OL',
'OPTGROUP', 'OPTION', 'P', 'PRE', 'SELECT', 'SPAN', 'STRONG', 'TABLE', 'TBODY',
'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TR', 'TT', 'UL'
], function(n) { window[n] = createDOMFunc(n); });
+34
View File
@@ -0,0 +1,34 @@
/**
Logging hooks for Firebug.
*/
useFireBug = true;
printfire = function() {
printfire.args = arguments;
// Opera8 does not support dispatchEvent()
// as global method (not required by W3C).
// This helps to sort it out.
try {
if (!useFireBug) {
// Mozilla installations without FireBug extension
throw 'useAlertFunction';
}
var ev = document.createEvent("Events");
ev.initEvent("printfire", false, true);
// FireBug needs dispatchEvent() to be global
// otherwise it fails
dispatchEvent(ev);
} catch (noConsole) {
alert(arguments[0]);
}
}
logFire = function() {
if (window.printfire) {
printfire( arguments[0], arguments[1]);
}
}
if (window['logger'] && logger.addListener) {
logger.addListener('firebug', null, function (msg) {
printfire(msg.level + sum(map(function (i) { return ', ' + i; }, msg.info)));
});
}
+290
View File
@@ -0,0 +1,290 @@
Array.prototype.exists = function (x) {
for (var i = 0; i < this.length; i++) {
if (this[i] == x) return true;
}
return false;
}
Date.prototype.formatDate = function (input,time) {
// formatDate :
// a PHP date like function, for formatting date strings
// See: http://www.php.net/date
//
// input : format string
// time : epoch time (seconds, and optional)
//
// if time is not passed, formatting is based on
// the current "this" date object's set time.
//
// supported:
// a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
// m, M, n, O, r, s, S, t, U, w, W, y, Y, z
//
// unsupported:
// I (capital i), T, Z
var switches = ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
"i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
"S", "t", "U", "w", "W", "y", "Y", "z"];
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"];
var daysShort = ["Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"];
var monthsShort = ["Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"];
var monthsLong = ["January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December"];
var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
"th", "th", "th", "th", "th", "th", "th", // 8th - 14th
"th", "th", "th", "th", "th", "th", "st", // 15th - 21st
"nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
"th", "th", "st"]; // 29th - 31st
function a() {
// Lowercase Ante meridiem and Post meridiem
return self.getHours() > 11? "pm" : "am";
}
function A() {
// Uppercase Ante meridiem and Post meridiem
return self.getHours() > 11? "PM" : "AM";
}
function B(){
// Swatch internet time. code simply grabbed from ppk,
// since I was feeling lazy:
// http://www.xs4all.nl/~ppk/js/beat.html
var off = (self.getTimezoneOffset() + 60)*60;
var theSeconds = (self.getHours() * 3600) +
(self.getMinutes() * 60) +
self.getSeconds() + off;
var beat = Math.floor(theSeconds/86.4);
if (beat > 1000) beat -= 1000;
if (beat < 0) beat += 1000;
if ((""+beat).length == 1) beat = "00"+beat;
if ((""+beat).length == 2) beat = "0"+beat;
return beat;
}
function d() {
// Day of the month, 2 digits with leading zeros
return new String(self.getDate()).length == 1?
"0"+self.getDate() : self.getDate();
}
function D() {
// A textual representation of a day, three letters
return daysShort[self.getDay()];
}
function F() {
// A full textual representation of a month
return monthsLong[self.getMonth()];
}
function g() {
// 12-hour format of an hour without leading zeros
return self.getHours() > 12? self.getHours()-12 : self.getHours();
}
function G() {
// 24-hour format of an hour without leading zeros
return self.getHours();
}
function h() {
// 12-hour format of an hour with leading zeros
if (self.getHours() > 12) {
var s = new String(self.getHours()-12);
return s.length == 1?
"0"+ (self.getHours()-12) : self.getHours()-12;
} else {
var s = new String(self.getHours());
return s.length == 1?
"0"+self.getHours() : self.getHours();
}
}
function H() {
// 24-hour format of an hour with leading zeros
return new String(self.getHours()).length == 1?
"0"+self.getHours() : self.getHours();
}
function i() {
// Minutes with leading zeros
return new String(self.getMinutes()).length == 1?
"0"+self.getMinutes() : self.getMinutes();
}
function j() {
// Day of the month without leading zeros
return self.getDate();
}
function l() {
// A full textual representation of the day of the week
return daysLong[self.getDay()];
}
function L() {
// leap year or not. 1 if leap year, 0 if not.
// the logic should match iso's 8601 standard.
var y_ = Y();
if (
(y_ % 4 == 0 && y_ % 100 != 0) ||
(y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
) {
return 1;
} else {
return 0;
}
}
function m() {
// Numeric representation of a month, with leading zeros
return self.getMonth() < 9?
"0"+(self.getMonth()+1) :
self.getMonth()+1;
}
function M() {
// A short textual representation of a month, three letters
return monthsShort[self.getMonth()];
}
function n() {
// Numeric representation of a month, without leading zeros
return self.getMonth()+1;
}
function O() {
// Difference to Greenwich time (GMT) in hours
var os = Math.abs(self.getTimezoneOffset());
var h = ""+Math.floor(os/60);
var m = ""+(os%60);
h.length == 1? h = "0"+h:1;
m.length == 1? m = "0"+m:1;
return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
}
function r() {
// RFC 822 formatted date
var r; // result
// Thu , 21 Dec 2000
r = D() + ", " + j() + " " + M() + " " + Y() +
// 16 : 01 : 07 +0200
" " + H() + ":" + i() + ":" + s() + " " + O();
return r;
}
function S() {
// English ordinal suffix for the day of the month, 2 characters
return daysSuffix[self.getDate()-1];
}
function s() {
// Seconds, with leading zeros
return new String(self.getSeconds()).length == 1?
"0"+self.getSeconds() : self.getSeconds();
}
function t() {
// thanks to Matt Bannon for some much needed code-fixes here!
var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
if (L()==1 && n()==2) return 29; // leap day
return daysinmonths[n()];
}
function U() {
// Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
return Math.round(self.getTime()/1000);
}
function W() {
// Weeknumber, as per ISO specification:
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
// if the day is three days before newyears eve,
// there's a chance it's "week 1" of next year.
// here we check for that.
var beforeNY = 364+L() - z();
var afterNY = z();
var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
if (beforeNY <= 2 && weekday <= 2-beforeNY) {
return 1;
}
// similarly, if the day is within threedays of newyears
// there's a chance it belongs in the old year.
var ny = new Date("January 1 " + Y() + " 00:00:00");
var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
if (
(afterNY <= 2) &&
(nyDay >=4) &&
(afterNY >= (6-nyDay))
) {
// Since I'm not sure we can just always return 53,
// i call the function here again, using the last day
// of the previous year, as the date, and then just
// return that week.
var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
return prevNY.formatDate("W");
}
// week 1, is the week that has the first thursday in it.
// note that this value is not zero index.
if (nyDay <= 3) {
// first day of the year fell on a thursday, or earlier.
return 1 + Math.floor( ( z() + nyDay ) / 7 );
} else {
// first day of the year fell on a friday, or later.
return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
}
}
function w() {
// Numeric representation of the day of the week
return self.getDay();
}
function Y() {
// A full numeric representation of a year, 4 digits
// we first check, if getFullYear is supported. if it
// is, we just use that. ppks code is nice, but wont
// work with dates outside 1900-2038, or something like that
if (self.getFullYear) {
var newDate = new Date("January 1 2001 00:00:00 +0000");
var x = newDate .getFullYear();
if (x == 2001) {
// i trust the method now
return self.getFullYear();
}
}
// else, do this:
// codes thanks to ppk:
// http://www.xs4all.nl/~ppk/js/introdate.html
var x = self.getYear();
var y = x % 100;
y += (y < 38) ? 2000 : 1900;
return y;
}
function y() {
// A two-digit representation of a year
var y = Y()+"";
return y.substring(y.length-2,y.length);
}
function z() {
// The day of the year, zero indexed! 0 through 366
var t = new Date("January 1 " + Y() + " 00:00:00");
var diff = self.getTime() - t.getTime();
return Math.floor(diff/1000/60/60/24);
}
var self = this;
if (time) {
// save time
var prevTime = self.getTime();
self.setTime(time);
}
var ia = input.split("");
var ij = 0;
while (ia[ij]) {
if (ia[ij] == "\\") {
// this is our way of allowing users to escape stuff
ia.splice(ij,1);
} else {
if (switches.exists(ia[ij])) {
ia[ij] = eval(ia[ij] + "()");
}
}
ij++;
}
// reset time, back to what it was
if (prevTime) {
self.setTime(prevTime);
}
return ia.join("");
}
+246
View File
@@ -0,0 +1,246 @@
/**
Play around with S3Ajax!
TODO: Remove Dojo dependency
*/
if (window.dojo) {
// dojo.setModulePrefix("dojo", "js/dojo");
// dojo.require("dojo.io.*");
// dojo.require("dojo.crypto.SHA1");
dojo.require("dojo.storage.*");
}
Play = {
/**
Initialize the play app.
*/
init: function() {
var _this = this;
S3Ajax.DEBUG = true;
// HACK: Wait for the storage flash to become available.
// TODO: Look for an official Dojo event to make this happen.
if (window.dojo) {
this._storage_wait = setInterval(function() {
if ($('dojo-storeContainer')) {
clearInterval(_this._storage_wait);
_this._storage_wait = null;
_this.recall();
}
}, 100);
}
},
/**
Make an attempt to recall S3 credentials.
*/
recall: function() {
if (window.dojo && dojo.storage.get('key_id', '/S3Ajax')) {
S3Ajax.KEY_ID = dojo.storage.get('key_id', '/S3Ajax');
S3Ajax.SECRET_KEY = dojo.storage.get('secret_key', '/S3Ajax');
$('key_id').value = S3Ajax.KEY_ID;
$('update_msg').innerHTML = 'Credentials fetched from local storage: '+(new Date());
// this.listbuckets();
// this.list();
}
},
/**
Accept new credentials from the form in the page.
*/
login: function() {
S3Ajax.KEY_ID = $('key_id').value;
S3Ajax.SECRET_KEY = $('secret_key').value;
// Try to stash the credentials away for next time.
if (window.dojo) {
dojo.storage.set('key_id', S3Ajax.KEY_ID, '/S3Ajax');
dojo.storage.set('secret_key', S3Ajax.SECRET_KEY, '/S3Ajax');
}
$('update_msg').innerHTML = 'Last updated: '+(new Date());
},
/**
Download the specified resource.
*/
download: function() {
var bucket = $('list_bucket').value;
var key = $('key').value;
$('content').value = "Loading...";
S3Ajax.get(bucket, key,
function(req, content) {
$('content').value = content;
$('xfer_msg').innerHTML = "Download succeeded at "+(new Date());
},
function(req, objc) {
$('xfer_msg').innerHTML = "Download failed at "+(new Date());
}
);
},
/**
Upload the specified resource.
*/
upload: function() {
var bucket = $('list_bucket').value;
var key = $('key').value;
var content = $('content').value;
S3Ajax.put(bucket, key, content,
function(req) {
$('xfer_msg').innerHTML = "Upload succeeded at "+(new Date());
},
function(req, obj) {
$('xfer_msg').innerHTML = "Upload failed at "+(new Date());
}
);
/*
S3Ajax.put(bucket, key, content,
{
content_type: "text/plain",
meta: {'posted-by':'S3Ajax'},
acl: "public-read",
},
function(req) {
$('xfer_msg').innerHTML = "Upload succeeded at "+(new Date());
},
function(req, obj) {
$('xfer_msg').innerHTML = "Upload failed at "+(new Date());
}
);
*/
},
/**
List available buckets
*/
listbuckets: function() {
var _this = this;
setList('buckets_list',['Loading...','']);
S3Ajax.listBuckets(
function(req, obj) {
clearList('buckets_list');
if (obj.ListAllMyBucketsResult) {
var buckets = obj.ListAllMyBucketsResult.Buckets.Bucket;
for (var i=0, bucket; bucket=buckets[i]; i++) {
addToList(
'buckets_list',
bucket.Name + ' ['+bucket.CreationDate+']',
bucket.Name
);
}
}
keys_list = null;
},
function(req) {
setList('buckets_list', ["Buckets list failed at "+(new Date()),'']);
}
);
},
/**
Change the current bucket to one selected in list.
*/
selectbucket: function() {
var sel = getSelected('buckets_list');
if (sel.length) $('list_bucket').value = sel[0];
},
/**
*/
deletebucket: function() {
var _this = this;
var sel = getSelected('buckets_list');
if (!sel.length) return;
setList('buckets_list',['Deleting...','']);
S3Ajax.deleteBucket(sel[0], function() {
_this.listbuckets();
});
},
/**
*/
createbucket: function() {
var _this = this;
var bucket = $('list_bucket').value;
setList('buckets_list',['Creating...','']);
S3Ajax.createBucket(bucket, function() {
_this.listbuckets();
});
},
/**
List a bucket's contents.
*/
list: function() {
var _this = this;
setList('keys_list', ['Loading...','']);
var bucket = $('list_bucket').value;
var params = {};
if ($('list_prefix').value) params['prefix'] = $('list_prefix').value;
if ($('list_maxkeys').value) params['max-keys'] = $('list_maxkeys').value;
if ($('list_marker').value) params['marker'] = $('list_marker').value;
S3Ajax.listKeys(bucket, params,
function(req, obj) {
clearList('keys_list');
var contents = obj.ListBucketResult.Contents;
for (var i=0, item; item=contents[i]; i++) {
addToList(
'keys_list',
/*item.LastModified + ' ' +*/ item.Key + ' (' + item.Size + ')',
item.Key
);
}
},
function(req, obj) {
setList('keys_list', ["Keys list failed at "+(new Date()),'']);
}
);
},
/**
Download the selected key.
*/
downloadSelectedKey: function() {
var sel = getSelected('keys_list');
if (sel.length) {
$('key').value = sel[0];
this.download();
}
},
/**
Delete seleted keys.
*/
deleteSelectedKeys: function() {
var _this = this;
var sel_keys = getSelected('keys_list');
if (!window.confirm("Delete " + sel_keys.length + " selected items?")) return;
S3Ajax.deleteKeys($('list_bucket').value, sel_keys,
function(key) { /*logFire("Deleted "+key);*/ },
function(req, obj) { /*logFire("Deleted all");*/ _this.list(); }
);
},
/* Help protect against errant end-commas */
EOF: null
}
addLoadEvent(function(){ Play.init() });
+202
View File
@@ -0,0 +1,202 @@
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
+9
View File
@@ -0,0 +1,9 @@
/**
S3AjaxWiki site-specific configuration
*/
with (S3AjaxWiki) {
DEBUG = true;
ANONYMOUS = true;
BUCKET = 's3wiki';
DEFAULT_ACL = 'public-read-write';
}
+573
View File
@@ -0,0 +1,573 @@
/**
S3AjaxWiki v0.1 - A client-side wiki for S3
http://decafbad.com/trac/wiki/S3Ajax
l.m.orchard@pobox.com
Share and Enjoy.
*/
/*
// TODO: Find a way to minimize the number of JS includes on wiki pages.
function $import() {
for (var i=0, path; path=arguments[i]; i++) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = path;
document.getElementsByTagName('head')[0].appendChild(script);
}
}
$import("js/firebug.js", "js/dojo.js", "js/sha1.js", "js/S3Ajax.js",
"js/wiky.js", "js/wiky.s3wiki.js");
*/
if (window.dojo) {
dojo.require("dojo.storage.*");
}
S3AjaxWiki = {
DEBUG: true,
ANONYMOUS: false,
BUCKET: 'decafbad',
TEMPLATE_KEY: 'wiki-template.html',
KEY_PREFIX: 'wiki/',
DEFAULT_ACL: 'public-read',
DEFAULT_TYPE: 'text/html',
DEFAULT_META: {'posted-by':'S3AjaxWiki'},
/*
These are the IDs of elements injected as a part of the wiki
editing framework, and should not end up in serialized pages.
*/
IGNORED_ELEMENT_IDS: [
'content_edit', 'credentials', 'toc', 'page_options',
'xfer_msg', 'dojo-storeContainer'
],
/*
These are attribute names that cause problems in MSIE.
We'll ignore them during page serialization.
TODO: Make this a per-element hash? Need more sophistication here.
*/
IGNORED_ATTRIBUTE_NAMES: [
'hideFocus', 'contentEditable', 'disabled', 'tabIndex',
'bottomMargin', 'noWrap', 'leftMargin', 'topMargin',
'rightMargin', 'defer'
],
/**
Initialize the wiki app
*/
init: function() {
// Debounce init calls.
if (arguments.callee.done) return;
arguments.callee.done = true;
S3Ajax.DEBUG = this.DEBUG;
S3Ajax.DEFEAT_CACHE = true;
forEach([ 'FIELDSET' ], function(n) {
window[n] = createDOMFunc(n);
});
this.injectEditingFramework();
if (!this.ANONYMOUS) this.autoLoadCredentials();
else this.onLogin();
},
/**
Try to load stored credentials when using dojo.storage.
TODO: Scoop out dojo.storage to work separately from dojo proper.
*/
autoLoadCredentials: function() {
var _this = this;
$('credentials_msg').innerHTML = 'No credentials.';
this.hideCredentials();
// HACK: Wait for the storage flash to become available.
// TODO: Look for an official Dojo event to make this happen.
this.hideCredentials();
if (window.dojo) {
this._storage_wait = setInterval(function() {
if ($('dojo-storeContainer')) {
clearInterval(_this._storage_wait);
_this._storage_wait = null;
try {
_this.recall();
} catch(e) {
}
}
}, 100);
} else {
this.onLogin();
}
},
/**
Some things to perform upon (un)successful login.
*/
onLogin: function() {
this.scanWikiWords();
this.refreshPageList();
},
/**
Scan wiki word links on the page, with the intent to discover
which actually exist.
*/
scanWikiWords: function() {
// Empty the list of words to scan
this._scan_words = {};
// Scan through wiki word links and gather unique list.
var links = document.getElementsByTagName('a');
for (var i=0, link; link=links[i]; i++) {
if ('wikiword' == link.className) {
this._scan_words[link.innerHTML] = true;
}
}
// Collect a plain list of unique words.
var words = [];
for (var word in this._scan_words) { words.push(word); }
this._doWordScan(words);
},
/**
Perform S3 HEAD requests to determine the existence of a given
list of wiki words. Collect the results, make a note of which
words exist or not.
*/
_doWordScan: function(words) {
var _this = this;
// If the words list is empty, stop.
if (!words.length) {
return this.updateWikiWords();
}
// Search for existence of a word, marking it appropriately.
var word = words.shift();
S3Ajax.head(this.BUCKET, this.KEY_PREFIX + word,
function() {
_this.markWikiWord(word, true);
_this._doWordScan(words);
},
function() {
_this.markWikiWord(word, false);
_this._doWordScan(words);
}
);
},
/**
Mark a given wiki word as found, or not.
*/
markWikiWord: function(word, found) {
this._scan_words[word] = found;
// HACK: Doing this for every found word might be too often.
this.updateWikiWords();
},
/**
Scan through wiki word links on the page. For every link not
found in S3, wire it up as a new page creation link.
*/
updateWikiWords: function() {
var links = document.getElementsByTagName('a');
for (var i=0, link; link=links[i]; i++) {
if ('wikiword' == link.className) {
var word = link.innerHTML;
if (!this._scan_words[word])
this.wireUpNewWord(link, word)
}
}
},
/**
Wire up a wiki word link as a new page creation link, changing
its CSS style and hooking its click event up to createNewPage().
*/
wireUpNewWord: function(link, word) {
var _this = this;
link.className = 'newword';
link.onclick = function() {
_this.createNewPage(word); return false;
}
},
/**
For a given wiki word, create a new page. Load up the wiki page
template, change the header and body titles, save to S3 as a new
key, redirect browser to the new page.
TODO: Simply redirect if the page already exists?
*/
createNewPage: function(word) {
// Do not create unnamed pages.
if (!word) return;
var _this = this;
S3Ajax.get(_this.BUCKET, _this.TEMPLATE_KEY,
function(req, data) {
var xml = getResponseXML(req);
// Update document head title
var page_title = xml.getElementsByTagName('title')[0];
page_title.firstChild.nodeValue = word;
// Update page header title.
/*
// HACK: Should getElementById work here? Seems not to.
var head_title = xml.getElementById('page_title');
head_title.nodeValue = word;
*/
var h1s = xml.getElementsByTagName('h1');
for (var i=0,h1; h1=h1s[i]; i++)
if ('page_title' == h1.getAttribute('id'))
h1.firstChild.nodeValue = word;
// Get serialized HTML content from the page DOM
var data = _this.fromDOMtoHTML(xml);
// Upload to S3, redirect if successful.
S3Ajax.put(_this.BUCKET, _this.KEY_PREFIX + word, data,
{
content_type: _this.DEFAULT_TYPE,
acl: _this.DEFAULT_ACL,
meta: _this.DEFAULT_META
},
function(req) {
location.href = word;
},
function(req, obj) {
$('xfer_msg').innerHTML = "Upload failed at "+(new Date());
}
);
},
function(req, data) {
// TODO: Do something useful on not finding the template.
$('xfer_msg').innerHTML = "Template fetch failed at "+(new Date());
}
);
},
/**
Refresh the list of available pages.
*/
refreshPageList: function() {
var _this = this;
setList('page_list', ['Loading...','']);
S3Ajax.listKeys(
this.BUCKET, { prefix:this.KEY_PREFIX },
function(req, obj) {
clearList('page_list');
// Sort in reverse-chronological change order.
var contents = obj.ListBucketResult.Contents;
contents.sort(function(a,b) {
if (b.LastModified > a.LastModified) return 1;
if (b.LastModified < a.LastModified) return -1;
return 0;
});
for (var i=0, item; item=contents[i]; i++) {
var key = item.Key;
var title = key.substr(_this.KEY_PREFIX.length)
addToList('page_list', title, key);
}
},
function(req, obj) {
setList('page_list', ['Failed to load list of pages.','']);
}
);
},
/**
Navigate to a new wiki page.
*/
selectPage: function(key) {
var _this = this;
if (!key) key = getSelected('page_list')[0];
// Page title is key, sans prefix
var title = (key.indexOf(_this.KEY_PREFIX) == 0) ?
key.substr(_this.KEY_PREFIX.length) : key;
location.href = title;
},
/**
*/
editPage: function() {
var content = $('content').innerHTML;
$('editor').value = Wiky.toWiki(content);
this.showEditor();
},
/**
*/
cancelEdit: function() {
this.hideEditor();
},
/**
*/
previewPage: function() {
var content = $('editor').value;
$('content').innerHTML = Wiky.toHtml(content);
this.scanWikiWords();
this.hideEditor();
},
/**
*/
updatePage: function(key) {
var _this = this;
if (!key) key = this.KEY_PREFIX + $('page_title').innerHTML;
// if (!key) key = getSelected('page_list')[0];
// Convert the wiki text to HTML and replace in page.
$('content').innerHTML = Wiky.toHtml($('editor').value);
this.hideEditor();
// Get serialized HTML content from the page DOM
var content = _this.fromDOMtoHTML();
// Upload to S3, redirect if successful.
S3Ajax.put(_this.BUCKET, key, content,
{
content_type: _this.DEFAULT_TYPE,
acl: _this.DEFAULT_ACL,
meta: {'posted-by':'S3AjaxWiki'}
},
function(req) {
_this.scanWikiWords();
$('xfer_msg').innerHTML = ""; // "Upload succeeded at "+(new Date());
},
function(req, obj) {
$('xfer_msg').innerHTML = "Upload failed at "+(new Date());
}
);
},
/**
Make an attempt to recall S3 credentials.
*/
recall: function() {
if (window.dojo) {
if (dojo.storage && dojo.storage.get && dojo.storage.get('key_id', '/S3Ajax')) {
S3Ajax.KEY_ID = dojo.storage.get('key_id', '/S3Ajax');
S3Ajax.SECRET_KEY = dojo.storage.get('secret_key', '/S3Ajax');
$('key_id').value = S3Ajax.KEY_ID;
$('credentials_msg').innerHTML = 'Credentials restored.';
this.hideCredentials();
this.onLogin();
}
}
},
/**
Accept new credentials from the form in the page.
*/
login: function() {
S3Ajax.KEY_ID = $('key_id').value;
S3Ajax.SECRET_KEY = $('secret_key').value;
// Try to stash the credentials away for next time.
if (window.dojo) {
dojo.storage.set('key_id', S3Ajax.KEY_ID, '/S3Ajax');
dojo.storage.set('secret_key', S3Ajax.SECRET_KEY, '/S3Ajax');
}
$('credentials_msg').innerHTML = 'Credentials supplied.';
this.hideCredentials();
this.onLogin();
},
showEditor: function() {
$('content_edit').style.display = "block";
$('content').style.display = "none";
},
hideEditor: function() {
$('content_edit').style.display = "none";
$('content').style.display = "";
},
showCredentials: function() {
$('credentials_fields').style.display = "block";
},
hideCredentials: function() {
$('credentials_fields').style.display = "none";
},
/**
Serialize a given DOM to HTML source. If no node given, assume
the current page should be serialized. Note that this makes efforts
using IGNORED_ELEMENT_IDS to avoid including the injected editor framework.
TODO: Steal more ideas from MochiKit.DOM.emitHTML()
*/
fromDOMtoHTML: function(node) {
if (!node) node = document;
switch (node.nodeType) {
case Node.DOCUMENT_NODE:
// HACK: Look for the first <html> in a document node.
return this.fromDOMtoHTML(node.getElementsByTagName('html')[0]);
case Node.TEXT_NODE:
return node.nodeValue;
case Node.ELEMENT_NODE:
var node_name = node.nodeName.toLowerCase();
// Skip elements with ignored IDs
for (var j=0, skip_id; skip_id=this.IGNORED_ELEMENT_IDS[j]; j++) {
if (skip_id == node.id) { return ''; }
}
// HACK: Firefox kept dropping in Firebug stylesheets
if ('link'==node_name && /chrome:/.test(node.getAttribute('href')))
return '';
// Start serializing the current node.
var out = '<' + node_name;
// Serialize the attributes of the node.
for (var i=0, attr; attr=node.attributes[i]; i++) {
var name = attr.name;
// Skip ignored attributes
var skip = false;
for (var j=0, skip_name; skip_name=this.IGNORED_ATTRIBUTE_NAMES[j]; j++) {
if (skip_name == name) { skip=true; break; }
}
if (skip) continue;
var value = attr.value;
if (value && value!=null && value!="null")
out += ' '+name+'="'+value+'"';
}
// Serialize all child nodes found.
var sub_out = '';
if ( ('script'==node_name || 'title'==node_name) && node.innerHTML) {
// HACK: MSIE gives me troubles in scooping out these tags contents.
sub_out = ''+node.innerHTML;
} else {
for (var i=0, child; child=node.childNodes[i]; i++) {
sub_out += this.fromDOMtoHTML(child);
}
}
// Finalize the current node.
if (sub_out || 'script'==node_name || 'title'==node_name)
return out + '>' + sub_out + '</' + node_name + '>';
else
return out + '/>';
default:
return '';
/*
// TODO: Err... Is this even what I should be doing here?
try {
return node.parentNode.innerHTML;
} catch (e) {
return '';
}
*/
}
},
/**
Build and inject the DOM structures necessary for editing
wiki pages. The events wired up are a little bit of a hack.
*/
injectEditingFramework: function() {
var body = document.getElementsByTagName('body')[0];
appendChildNodes(body, [
// Build the content editing form.
FORM({"id":"content_edit", "onsubmit":"return false"},
TEXTAREA({"id":"editor", "name":"editor", "cols":"80", "rows":"20"}),
BR(),
FIELDSET({},
BUTTON({"id":"preview", "onclick":"S3AjaxWiki.previewPage(); return false"}, "Preview Changes"),
BUTTON({"id":"submit", "onclick":"S3AjaxWiki.updatePage(); return false"}, "Save Changes"),
BUTTON({"id":"cancel", "onclick":"S3AjaxWiki.cancelEdit(); return false"}, "Cancel")
)
),
// Build the login credentials form.
(this.ANONYMOUS) ? '' :
FORM({"id":"credentials", "onsubmit":"S3AjaxWiki.login(); return false;"},
DIV({"id":"cals_status"},
SPAN({"id":"credentials_msg"}),
" ",
A({"href":"#", "onclick":"S3AjaxWiki.showCredentials(); return false"}, "Login.")
),
FIELDSET({"id":"credentials_fields"},
LEGEND({}, "Credentials"),
LABEL({"for":"key_id"}, "AWSAccessKey"), BR(),
INPUT({"type":"text", "size":"25", "id":"key_id", "name":"key_id"}), BR(),
LABEL({"for":"secret_key"}, "SecretAccessKey"), BR(),
INPUT({"type":"password", "size":"25", "id":"secret_key", "name":"secret_key"}), BR(),
BUTTON({"id":"store", "onclick":"S3AjaxWiki.login(); return false"}, " Store "),
BUTTON({"id":"recall", "onclick":"S3AjaxWiki.recall(); return false"}, " Recall "),
BUTTON({"id":"cancel", "onclick":"S3AjaxWiki.hideCredentials(); return false"}, " Cancel ")
)
),
// Build the page list box.
FORM({'id':'toc', 'onsubmit':'return false'},
"Recent Changes: ", /* BR(), */
SELECT({'id':'page_list', 'name':'page_list', 'onchange':'S3AjaxWiki.selectPage(); return false'}),
BUTTON({'id':'get_pages', 'onclick':'S3AjaxWiki.selectPage(); return false'}, 'Go' ) /*,
BUTTON({'id':'list_pages', 'onclick':'S3AjaxWiki.refreshPageList(); return false'}, 'Refresh' )
*/
),
// Set up the page options div
FORM({'id':'page_options', 'onsubmit':'return false'},
BUTTON({'onclick':'S3AjaxWiki.editPage(); return false;'}, "Edit Page"),
" | ",
INPUT({'type':'text', 'size':'15', 'id':'new_page_name', 'name':'new_page_name', 'value':'NewPage'}),
BUTTON({'onclick':'S3AjaxWiki.createNewPage($("new_page_name").value); return false;'}, "Create Page")
),
// Inject the xfer message div.
SPAN({'id':'xfer_msg'})
]);
},
/* Help protect against errant end-commas */
EOF: null
};
/**
Schedule the whole mess to fire up on load.
*/
addLoadEvent(function(){ S3AjaxWiki.init() });
+373
View File
@@ -0,0 +1,373 @@
/* This work is licensed under Creative Commons GNU LGPL License.
License: http://creativecommons.org/licenses/LGPL/2.1/
Author: Stefan Goessner/2005-06
Web: http://goessner.net/
*/
var Wiky = {
version: 0.95,
blocks: null,
rules: {
all: [
"Wiky.rules.pre",
"Wiky.rules.nonwikiblocks",
"Wiky.rules.wikiblocks",
"Wiky.rules.post",
],
pre: [
{ rex:/(\r?\n)/g, tmplt:"\xB6" }, // replace line breaks with '¶' ..
],
post: [
{ rex:/(^\xB6)|(\xB6$)/g, tmplt:"" }, // .. remove linebreaks at BOS and EOS ..
{ rex:/@([0-9]+)@/g, tmplt:function($0,$1){return Wiky.restore($1);} }, // resolve blocks ..
{ rex:/\xB6/g, tmplt:"\n" } // replace '¶' with line breaks ..
],
nonwikiblocks: [
{ rex:/\\([%])/g, tmplt:function($0,$1){return Wiky.store($1);} },
{ rex:/\[(?:\{([^}]*)\})?(?:\(([^)]*)\))?%(.*?)%\]/g, tmplt:function($0,$1,$2,$3){return ":p]"+Wiky.store("<pre"+($2?(" lang=\"x-"+Wiky.attr($2)+"\""):"")+Wiky.style($1)+">" + Wiky.apply($3, $2?Wiky.rules.lang[Wiky.attr($2)]:Wiky.rules.code) + "</pre>")+"[p:";} } //programm code block
],
wikiblocks: [
"Wiky.rules.nonwikiinlines",
"Wiky.rules.escapes",
{ rex:/(?:^|\xB6)(={1,6})(.*?)[=]*(?=\xB6|$)/g, tmplt:function($0,$1,$2){ var h=$1.length; return ":p]\xB6<h"+h+">"+$2+"</h"+h+">\xB6[p:";} }, // <h1> .. <h6>
{ rex:/(?:^|\xB6)[-]{4}(?:\xB6|$)/g, tmplt:"\xB6<hr/>\xB6" }, // horizontal ruler ..
{ rex:/\\\\([ \xB6])/g, tmplt:"<br/>$1" }, // forced line break ..
{ rex:/(^|\xB6)([*01aAiIg]*[\.*])[ ]/g, tmplt:function($0,$1,$2){var state=$2.replace(/([*])/g,"u").replace(/([\.])/,"");return ":"+state+"]"+$1+"["+state+":";}},
{ rex:/(?:^|\xB6);[ ](.*?):[ ]/g, tmplt:"\xB6:l][l:$1:d][d:"}, // ; term : definition
{ rex:/\[(?:\{([^}]*)\})?(?:\(([^)]*)\))?\"/g, tmplt:function($0,$1,$2){return ":p]<blockquote"+Wiky.attr($2,"cite",0)+Wiky.attr($2,"title",1)+Wiky.style($1)+">[p:"; } }, // block quotation start
{ rex:/\"\]/g, tmplt:":p]</blockquote>[p:" }, // block quotation end
{ rex:/\[(\{[^}]*\})?\|/g, tmplt:":t]$1[r:" }, // .. start table ..
{ rex:/\|\]/g, tmplt:":r][t:" }, // .. end table ..
{ rex:/\|\xB6[ ]?\|/g, tmplt:":r]\xB6[r:" }, // .. end/start table row ..
{ rex:/\|/g, tmplt:":c][c:" }, // .. end/start table cell ..
{ rex:/^(.*)$/g, tmplt:"[p:$1:p]" }, // start paragraph '[p:' at BOS .. end paragraph ':p]' at EOS ..
{ rex:/(([\xB6])([ \t\f\v\xB6]*?)){2,}/g, tmplt:":p]$1[p:" }, // .. separate paragraphs at blank lines ..
{ rex:/\[([01AIacdgilprtu]+)[:](.*?)[:]([01AIacdgilprtu]+)\]/g, tmplt:function($0,$1,$2,$3){return Wiky.sectionRule($1==undefined?"":$1,"",Wiky.apply($2,Wiky.rules.wikiinlines),!$3?"":$3);} },
{ rex:/\[[01AIacdgilprtu]+[:]|[:][01AIacdgilprtu]+\]/g, tmplt:"" }, // .. remove singular section delimiters (they frequently exist with incomplete documents while typing) ..
{ rex:/<td>(?:([0-9]*)[>])?([ ]?)(.*?)([ ]?)<\/td>/g, tmplt:function($0,$1,$2,$3,$4){return "<td"+($1?" colspan=\""+$1+"\"":"")+($2==" "?(" style=\"text-align:"+($2==$4?"center":"right")+";\""):($4==" "?" style=\"text-align:left;\"":""))+">"+$2+$3+$4+"</td>";} },
{ rex:/<(p|table)>(?:\xB6)?(?:\{(.*?)\})/g, tmplt:function($0,$1,$2){return "<"+$1+Wiky.style($2)+">";} },
{ rex:/<p>([ \t\f\v\xB6]*?)<\/p>/g, tmplt:"$1" }, // .. remove empty paragraphs ..
"Wiky.rules.shortcuts"
],
nonwikiinlines: [
{ rex:/%(?:\{([^}]*)\})?(?:\(([^)]*)\))?(.*?)%/g, tmplt:function($0,$1,$2,$3){return Wiky.store("<code"+($2?(" lang=\"x-"+Wiky.attr($2)+"\""):"")+Wiky.style($1)+">" + Wiky.apply($3, $2?Wiky.rules.lang[Wiky.attr($2)]:Wiky.rules.code) + "</code>");} }, // inline code
{ rex:/%(.*?)%/g, tmplt:function($0,$1){return Wiky.store("<code>" + Wiky.apply($2, Wiky.rules.code) + "</code>");} }
],
wikiinlines: [
{ rex:/\*([^*]+)\*/g, tmplt:"<strong>$1</strong>" }, // .. strong ..
{ rex:/_([^_]+)_/g, tmplt:"<em>$1</em>" },
{ rex:/\^([^^]+)\^/g, tmplt:"<sup>$1</sup>" },
{ rex:/~([^~]+)~/g, tmplt:"<sub>$1</sub>" },
{ rex:/\(-(.+?)-\)/g, tmplt:"<del>$1</del>" },
{ rex:/\?([^ \t\f\v\xB6]+)\((.+)\)\?/g, tmplt:"<abbr title=\"$2\">$1</abbr>" }, // .. abbreviation ..
{ rex:/\[(?:\{([^}]*)\})?[Ii]ma?ge?\:([^ ,\]]*)(?:[, ]([^\]]*))?\]/g, tmplt:function($0,$1,$2,$3){return Wiky.store("<img"+Wiky.style($1)+" src=\""+$2+"\" alt=\""+($3?$3:$2)+"\" title=\""+($3?$3:$2)+"\"/>");} }, // wikimedia image style ..
{ rex:/\[([^ ,]+)[, ]([^\]]*)\]/g, tmplt:function($0,$1,$2){return Wiky.store("<a href=\""+$1+"\">"+$2+"</a>");}}, // wiki block style uri's ..
{ rex:/(((http(s?))\:\/\/)?[A-Za-z0-9\._\/~\-:]+\.(?:png|jpg|jpeg|gif|bmp))/g, tmplt:function($0,$1,$2){return Wiky.store("<img src=\""+$1+"\" alt=\""+$1+"\"/>");} }, // simple images ..
{ rex:/((mailto\:|javascript\:|(news|file|(ht|f)tp(s?))\:\/\/)[A-Za-z0-9\.:_\/~%\-+&#?!=()@\x80-\xB5\xB7\xFF]+)/g, tmplt:"<a href=\"$1\">$1</a>" } // simple uri's ..
],
escapes: [
{ rex:/\\([|*_~\^])/g, tmplt:function($0,$1){return Wiky.store($1);} },
{ rex:/\\&/g, tmplt:"&amp;" },
{ rex:/\\>/g, tmplt:"&gt;" },
{ rex:/\\</g, tmplt:"&lt;" }
],
shortcuts: [
{ rex:/---/g, tmplt:"&#8212;" }, // &mdash;
{ rex:/--/g, tmplt:"&#8211;" }, // &ndash;
{ rex:/[\.]{3}/g, tmplt:"&#8230;"}, // &hellip;
{ rex:/<->/g, tmplt:"&#8596;"}, // $harr;
{ rex:/<-/g, tmplt:"&#8592;"}, // &larr;
{ rex:/->/g, tmplt:"&#8594;"}, //&rarr;
],
code: [
{ rex:/&/g, tmplt:"&amp;"},
{ rex:/</g, tmplt:"&lt;"},
{ rex:/>/g, tmplt:"&gt;"}
],
lang: {}
},
inverse: {
all: [
"Wiky.inverse.pre",
"Wiky.inverse.nonwikiblocks",
"Wiky.inverse.wikiblocks",
"Wiky.inverse.post"
],
pre: [
{ rex:/(\r?\n)/g, tmplt:"\xB6" } // replace line breaks with '¶' ..
],
post: [
{ rex:/@([0-9]+)@/g, tmplt:function($0,$1){return Wiky.restore($1);} }, // resolve blocks ..
{ rex:/\xB6/g, tmplt:"\n" } // replace '¶' with line breaks ..
],
nonwikiblocks: [
{ rex:/<pre([^>]*)>(.*?)<\/pre>/mgi, tmplt:function($0,$1,$2){return Wiky.store("["+Wiky.invStyle($1)+Wiky.invAttr($1,["lang"]).replace(/x\-/,"")+"%"+Wiky.apply($2, Wiky.hasAttr($1,"lang")?Wiky.inverse.lang[Wiky.attrVal($1,"lang").substr(2)]:Wiky.inverse.code)+"%]");} } //code block
],
wikiblocks: [
"Wiky.inverse.nonwikiinlines",
"Wiky.inverse.escapes",
"Wiky.inverse.wikiinlines",
{ rex:/<h1>(.*?)<\/h1>/mgi, tmplt:"=$1=" },
{ rex:/<h2>(.*?)<\/h2>/mgi, tmplt:"==$1==" },
{ rex:/<h3>(.*?)<\/h3>/mgi, tmplt:"===$1===" },
{ rex:/<h4>(.*?)<\/h4>/mgi, tmplt:"====$1====" },
{ rex:/<h5>(.*?)<\/h5>/mgi, tmplt:"=====$1=====" },
{ rex:/<h6>(.*?)<\/h6>/mgi, tmplt:"======$1======" },
{ rex:/<(p|table)[^>]+(style=\"[^\"]*\")[^>]*>/mgi, tmplt:function($0,$1,$2){return "<"+$1+">"+Wiky.invStyle($2);} },
{ rex:/\xB6{2}<li/mgi, tmplt:"\xB6<li" }, // ie6 only ..
{ rex:/<li class=\"?([^ >\"]*)\"?[^>]*?>([^<]*)/mgi, tmplt:function($0,$1,$2){return $1.replace(/u/g,"*").replace(/([01aAiIg])$/,"$1.")+" "+$2;}}, // list items ..
{ rex:/(^|\xB6)<(u|o)l[^>]*?>\xB6/mgi, tmplt:"$1" }, // only outer level list start at BOL ...
{ rex:/(<\/(?:dl|ol|ul|p)>[ \xB6]*<(?:p)>)/gi, tmplt:"\xB6\xB6" },
{ rex:/<dt>(.*?)<\/dt>[ \f\n\r\t\v]*<dd>/mgi, tmplt:"; $1: " },
{ rex:/<blockquote([^>]*)>/mgi, tmplt:function($0,$1){return Wiky.store("["+Wiky.invStyle($1)+Wiky.invAttr($1,["cite","title"])+"\"");} },
{ rex:/<\/blockquote>/mgi, tmplt:"\"]" },
{ rex:/<td class=\"?lft\"?>\xB6*[ ]?|<\/tr>/mgi, tmplt:"|" }, // ie6 only ..
{ rex:/\xB6<tr(?:[^>]*?)>/mgi, tmplt:"\xB6" },
{ rex:/<td colspan=\"([0-9]+)\"(?:[^>]*?)>/mgi, tmplt:"|$1>" },
{ rex:/<td(?:[^>]*?)>/mgi, tmplt:"|" },
{ rex:/<table>/mgi, tmplt:"[" },
{ rex:/<\/table>/mgi, tmplt:"]" },
{ rex:/<tr(?:[^>]*?)>\xB6*|<\/td>\xB6*|<tbody>\xB6*|<\/tbody>/mgi, tmplt:"" },
{ rex:/<hr\/?>/mgi, tmplt:"----" },
{ rex:/<br\/?>/mgi, tmplt:"\\\\" },
{ rex:/(<p>|<(d|o|u)l[^>]*>|<\/(dl|ol|ul|p)>|<\/(li|dd)>)/mgi, tmplt:"" },
"Wiky.inverse.shortcuts"
],
nonwikiinlines: [
{ rex:/<code>(.*?)<\/code>/g, tmplt:function($0,$1){return Wiky.store("%"+Wiky.apply($1, Wiky.inverse["code"])+"%");} }
],
wikiinlines: [
{ rex:/<strong[^>]*?>(.*?)<\/strong>/mgi, tmplt:"*$1*" },
{ rex:/<b[^>]*?>(.*?)<\/b>/mgi, tmplt:"*$1*" },
{ rex:/<em[^>]*?>(.*?)<\/em>/mgi, tmplt:"_$1_" },
{ rex:/<i[^>]*?>(.*?)<\/i>/mgi, tmplt:"_$1_" },
{ rex:/<sup[^>]*?>(.*?)<\/sup>/mgi, tmplt:"^$1^" },
{ rex:/<sub[^>]*?>(.*?)<\/sub>/mgi, tmplt:"~$1~" },
{ rex:/<del[^>]*?>(.*?)<\/del>/mgi, tmplt:"(-$1-)" },
{ rex:/<abbr title=\"([^\"]*)\">(.*?)<\/abbr>/mgi, tmplt:"?$2($1)?" },
{ rex:/<a href=\"([^\"]*)\"[^>]*?>(.*?)<\/a>/mgi, tmplt:function($0,$1,$2){return $1==$2?$1:"["+$1+","+$2+"]";}},
{ rex:/<img([^>]*)\/>/mgi, tmplt:function($0,$1){var a=Wiky.attrVal($1,"alt"),h=Wiky.attrVal($1,"src"),t=Wiky.attrVal($1,"title"),s=Wiky.attrVal($1,"style");return s||(t&&h!=t)?("["+Wiky.invStyle($1)+"img:"+h+(t&&(","+t))+"]"):h;}},
],
escapes: [
{ rex:/([|*_~%\^])/g, tmplt:"\\$1" },
{ rex:/&amp;/g, tmplt:"\\&" },
{ rex:/&gt;/g, tmplt:"\\>" },
{ rex:/&lt;/g, tmplt:"\\<" }
],
shortcuts: [
{ rex:/&#8211;|\u2013/g, tmplt:"--"},
{ rex:/&#8212;|\u2014/g, tmplt:"---"},
{ rex:/&#8230;|\u2026/g, tmplt:"..."},
{ rex:/&#8596;|\u2194/g, tmplt:"<->"},
{ rex:/&#8592;|\u2190/g, tmplt:"<-"},
{ rex:/&#8594;|\u2192/g, tmplt:"->"}
],
code: [
{ rex:/&amp;/g, tmplt:"&"},
{ rex:/&lt;/g, tmplt:"<"},
{ rex:/&gt;/g, tmplt:">"}
],
lang: {}
},
toHtml: function(str) {
Wiky.blocks = [];
return Wiky.apply(str, Wiky.rules.all);
},
toWiki: function(str) {
Wiky.blocks = [];
return Wiky.apply(str, Wiky.inverse.all);
},
apply: function(str, rules) {
if (str && rules)
for (var i in rules) {
if (typeof(rules[i]) == "string")
str = Wiky.apply(str, eval(rules[i]));
else
str = str.replace(rules[i].rex, rules[i].tmplt);
}
return str;
},
store: function(str, unresolved) {
return unresolved ? "@" + (Wiky.blocks.push(str)-1) + "@"
: "@" + (Wiky.blocks.push(str.replace(/@([0-9]+)@/g, function($0,$1){return Wiky.restore($1);}))-1) + "@";
},
restore: function(idx) {
return Wiky.blocks[idx];
},
attr: function(str, name, idx) {
var a = str && str.split(",")[idx||0];
return a ? (name ? (" "+name+"=\""+a+"\"") : a) : "";
},
hasAttr: function(str, name) {
return new RegExp(name+"=").test(str);
},
attrVal: function(str, name) {
return str.replace(new RegExp("^.*?"+name+"=\"(.*?)\".*?$"), "$1");
},
invAttr: function(str, names) {
var a=[], x;
for (var i in names)
if (str.indexOf(names[i]+"=")>=0)
a.push(str.replace(new RegExp("^.*?"+names[i]+"=\"(.*?)\".*?$"), "$1"));
return a.length ? ("("+a.join(",")+")") : "";
},
style: function(str) {
var s = str && str.split(/,|;/), p, style = "";
for (var i in s) {
p = s[i].split(":");
if (p[0] == ">") style += "margin-left:4em;";
else if (p[0] == "<") style += "margin-right:4em;";
else if (p[0] == ">>") style += "float:right;";
else if (p[0] == "<<") style += "float:left;";
else if (p[0] == "=") style += "display:block;margin:0 auto;";
else if (p[0] == "_") style += "text-decoration:underline;";
else if (p[0] == "b") style += "border:solid 1px;";
else if (p[0] == "c") style += "color:"+p[1]+";";
else if (p[0] == "C") style += "background:"+p[1]+";";
else if (p[0] == "w") style += "width:"+p[1]+";";
else style += p[0]+":"+p[1]+";";
}
return style ? " style=\""+style+"\"" : "";
},
invStyle: function(str) {
var s = /style=/.test(str) ? str.replace(/^.*?style=\"(.*?)\".*?$/, "$1") : "",
p = s && s.split(";"), pi, prop = [];
for (var i in p) {
pi = p[i].split(":");
if (pi[0] == "margin-left" && pi[1]=="4em") prop.push(">");
else if (pi[0] == "margin-right" && pi[1]=="4em") prop.push("<");
else if (pi[0] == "float" && pi[1]=="right") prop.push(">>");
else if (pi[0] == "float" && pi[1]=="left") prop.push("<<");
else if (pi[0] == "margin" && pi[1]=="0 auto") prop.push("=");
else if (pi[0] == "display" && pi[1]=="block") ;
else if (pi[0] == "text-decoration" && pi[1]=="underline") prop.push("_");
else if (pi[0] == "border" && pi[1]=="solid 1px") prop.push("b");
else if (pi[0] == "color") prop.push("c:"+pi[1]);
else if (pi[0] == "background") prop.push("C:"+pi[1]);
else if (pi[0] == "width") prop.push("w:"+pi[1]);
else if (pi[0]) prop.push(pi[0]+":"+pi[1]);
}
return prop.length ? ("{" + prop.join(",") + "}") : "";
},
sectionRule: function(fromLevel, style, content, toLevel) {
var trf = { p_p: "<p>$1</p>",
p_u: "<p>$1</p><ul$3>",
p_o: "<p>$1</p><ol$3>",
// p - ul
// ul - p
u_p: "<li$2>$1</li></ul>",
u_c: "<li$2>$1</li></ul></td>",
u_r: "<li$2>$1</li></ul></td></tr>",
uu_p: "<li$2>$1</li></ul></li></ul>",
uo_p: "<li$2>$1</li></ol></li></ul>",
uuu_p: "<li$2>$1</li></ul></li></ul></li></ul>",
uou_p: "<li$2>$1</li></ul></li></ol></li></ul>",
uuo_p: "<li$2>$1</li></ol></li></ul></li></ul>",
uoo_p: "<li$2>$1</li></ol></li></ol></li></ul>",
// ul - ul
u_u: "<li$2>$1</li>",
uu_u: "<li$2>$1</li></ul></li>",
uo_u: "<li$2>$1</li></ol></li>",
uuu_u: "<li$2>$1</li></ul></li></ul></li>",
uou_u: "<li$2>$1</li></ul></li></ol></li>",
uuo_u: "<li$2>$1</li></ol></li></ul></li>",
uoo_u: "<li$2>$1</li></ol></li></ol></li>",
u_uu: "<li$2>$1<ul$3>",
// ul - ol
u_o: "<li$2>$1</li></ul><ol$3>",
uu_o: "<li$2>$1</li></ul></li></ul><ol$3>",
uo_o: "<li$2>$1</li></ol></li></ul><ol$3>",
uuu_o: "<li$2>$1</li></ul></li></ul></li></ul><ol$3>",
uou_o: "<li$2>$1</li></ul></li></ol></li></ul><ol$3>",
uuo_o: "<li$2>$1</li></ol></li></ul></li></ul><ol$3>",
uoo_o: "<li$2>$1</li></ol></li></ol></li></ul><ol$3>",
u_uo: "<li$2>$1<ol$3>",
// ol - p
o_p: "<li$2>$1</li></ol>",
oo_p: "<li$2>$1</li></ol></li></ol>",
ou_p: "<li$2>$1</li></ul></li></ol>",
ooo_p: "<li$2>$1</li></ol></li></ol>",
ouo_p: "<li$2>$1</li></ol></li></ul></li></ol>",
oou_p: "<li$2>$1</li></ul></li></ol></li></ol>",
ouu_p: "<li$2>$1</li></ul></li></ul></li></ol>",
// ol - ul
o_u: "<li$2>$1</li></ol><ul$3>",
oo_u: "<li$2>$1</li></ol></li></ol><ul$3>",
ou_u: "<li$2>$1</li></ul></li></ol><ul$3>",
ooo_u: "<li$2>$1</li></ol></li></ol></li></ol><ul$3>",
ouo_u: "<li$2>$1</li></ol></li></ul></li></ol><ul$3>",
oou_u: "<li$2>$1</li></ul></li></ol></li></ol><ul$3>",
ouu_u: "<li$2>$1</li></ul></li></ul></li></ol><ul$3>",
o_ou: "<li$2>$1<ul$3>",
// -- ol - ol --
o_o: "<li$2>$1</li>",
oo_o: "<li$2>$1</li></ol></li>",
ou_o: "<li$2>$1</li></ul></li>",
ooo_o: "<li$2>$1</li></ol></li></ol></li>",
ouo_o: "<li$2>$1</li></ol></li></ul></li>",
oou_o: "<li$2>$1</li></ul></li></ol></li>",
ouu_o: "<li$2>$1</li></ul></li></ul></li>",
o_oo: "<li$2>$1<ol$3>",
// -- dl --
l_d: "<dt>$1</dt>",
d_l: "<dd>$1</dd>",
d_u: "<dd>$1</dd></dl><ul>",
d_o: "<dd>$1</dd></dl><ol>",
p_l: "<p>$1</p><dl>",
u_l: "<li$2>$1</li></ul><dl>",
o_l: "<li$2>$1</li></ol><dl>",
uu_l: "<li$2>$1</li></ul></li></ul><dl>",
uo_l: "<li$2>$1</li></ol></li></ul><dl>",
ou_l: "<li$2>$1</li></ul></li></ol><dl>",
oo_l: "<li$2>$1</li></ol></li></ol><dl>",
d_p: "<dd>$1</dd></dl>",
// -- table --
p_t: "<p>$1</p><table>",
p_r: "<p>$1</p></td></tr>",
p_c: "<p>$1</p></td>",
t_p: "</table><p>$1</p>",
r_r: "<tr><td>$1</td></tr>",
r_p: "<tr><td><p>$1</p>",
r_c: "<tr><td>$1</td>",
r_u: "<tr><td>$1<ul>",
c_p: "<td><p>$1</p>",
c_r: "<td>$1</td></tr>",
c_c: "<td>$1</td>",
// c_u: "<td>$1<ul>",
u_t: "<li$2>$1</li></ul><table>",
o_t: "<li$2>$1</li></ol><table>",
d_t: "<dd>$1</dd></dl><table>",
t_u: "</table><p>$1</p><ul>",
t_o: "</table><p>$1</p><ol>",
t_l: "</table><p>$1</p><dl>"
};
var type = { "0": "decimal-leading-zero",
"1": "decimal",
"a": "lower-alpha",
"A": "upper-alpha",
"i": "lower-roman",
"I": "upper-roman",
"g": "lower-greek" };
var from = "", to = "", maxlen = Math.max(fromLevel.length, toLevel.length), sync = true, sectiontype = type[toLevel.charAt(toLevel.length-1)], transition;
for (var i=0; i<maxlen; i++)
if (fromLevel.charAt(i+1) != toLevel.charAt(i+1) || !sync || i == maxlen-1)
{
from += fromLevel.charAt(i) == undefined ? " " : fromLevel.charAt(i);
to += toLevel.charAt(i) == undefined ? " " : toLevel.charAt(i);
sync = false;
}
transition = (from + "_" + to).replace(/([01AIagi])/g, "o");
return !trf[transition] ? ("?(" + transition + ")") // error string !
: trf[transition].replace(/\$2/, " class=\"" + fromLevel + "\"")
.replace(/\$3/, !sectiontype ? "" : (" style=\"list-style-type:" + sectiontype + ";\""))
.replace(/\$1/, content)
.replace(/<p><\/p>/, "");
}
}
+40
View File
@@ -0,0 +1,40 @@
/* This work is licensed under Creative Commons GNU LGPL License.
License: http://creativecommons.org/licenses/LGPL/2.1/
Author: Stefan Goessner/2005-06
Web: http://goessner.net/
credits: http://www.regular-expressions.info/examplesprogrammer.html
*/
Wiky.rules.lang.js = [
"Wiky.rules.code",
{ rex:/"([^"\\\xB6]*(\\.[^"\\\xB6]*)*)"/g, tmplt:function($0,$1){return Wiky.store("<span class=\"str\">\""+$1+"\"</span>");}}, // string delimited by '"' with '\"' allowed ..
{ rex:/'([^'\\\xB6]*(\\.[^'\\\xB6]*)*)'/g, tmplt:function($0,$1){return Wiky.store("<span class=\"str\">\'"+$1+"\'</span>");}}, // string delimited by "'" with "\'" allowed ..
{ rex:/\/\/(.*?)(?:\xB6|$)/g, tmplt:function($0,$1){return Wiky.store("<span class\=\"cmt\">//"+$1+"</span>\xB6");}}, // single line comment
{ rex:/\/\*(.*?)\*\//g, tmplt:function($0,$1){return Wiky.store("<span class\=\"cmt\">\/*"+$1+"*\/</span>");}}, // multi-line comment
// { rex:/([\]\[\-+\|*!%<>=\{\}?:,\)\(]+)|(&#34;|&#47;|&#61;)+/g, tmplt:"<span class=\"op\">$1</span>"}, // operators
{ rex:/\b(break|case|catch|continue|do|else|false|for|function|if|in|new|return|switch|this|throw|true|try|var|while|with)\b/g, tmplt:"<span class=\"kwd\">$1</span>" }, // keywords
{ rex:/\b(arguments|Array|Boolean|Date|Error|Function|Global|Math|Number|Object|RegExp|String)\b/g, tmplt:"<span class=\"obj\">$1</span>" }, // objects
{ rex:/\.(abs|acos|anchor|arguments|asin|atan|atan2|big|blink|bold|callee|caller|ceil|charAt|charCodeAt|concat|constructor|cos|E|escape|eval|exp|fixed|floor|fontcolor|fontsize|fromCharCode|getDate|getDay|getFullYear|getHours|getMilliseconds|getMinutes|getMonth|getSeconds|getTime|getTimezoneOffset|getUTCDate|getUTCDay|getUTCFullYear|getUTCHours|getUTCMilliseconds|getUTCMinutes|getUTCMonth|getUTCSeconds|getVarDate|getYear|index|indexOf|Infinity|input|isFinite|isNaN|italics|join|lastIndex|lastIndexOf|lastMatch|lastParen|leftContext|length|link|LN10|LN2|log|LOG10E|LOG2E|match|max|MAX_VALUE|min|MIN_VALUE|NaN|NaN|NEGATIVE_INFINITY|parse|parseFloat|parseInt|PI|pop|POSITIVE_INFINITY|pow|prototype|push|random|replace|reverse|rightContext|round|search|setDate|setFullYear|setHours|setMilliseconds|setMinutes|setMonth|setSeconds|setTime|setUTCDate|setUTCFullYear|setUTCHours|setUTCMilliseconds|setUTCMinutes|setUTCMonth|setUTCSeconds|setYear|shift|sin|slice|slice|small|sort|splice|split|sqrt|SQRT1_2|SQRT2|strike|sub|substr|substring|sup|tan|toGMTString|toLocaleString|toLowerCase|toString|toUpperCase|toUTCString|unescape|unshift|UTC|valueOf)\b/g, tmplt:".<span class=\"mbr\">$1</span>" }, // members
];
Wiky.rules.lang.xml = [
{ rex:/<script([^>]*)>(.*?)<\/script>/g, tmplt:function($0,$1,$2){return "<script"+$1+">"+Wiky.store(Wiky.apply($2, Wiky.rules.lang.js))+"</script>";} }, // script blocks ..
{ rex:/<!\[CDATA\[(.*?)\]\]>/g, tmplt:function($0,$1){return Wiky.store("&lt;![CDATA["+$1+"]]&gt;");} }, // CDATA sections, ..
{ rex:/<!(.*?)>/g, tmplt:function($0,$1){return Wiky.store("<span class=\"cmt\">&lt;!"+$1+"&gt;</span>");} }, // inline xml comments, doctypes, ..
{ rex:/</g, tmplt:"\xAB"}, // replace '<' by '«'
{ rex:/>/g, tmplt:"\xBB"}, // replace '>' by '»'
{ rex:/([-A-Za-z0-9_:]+)[ ]*=[ ]*\"(.*?)\"/g, tmplt:"<span class=\"xnam\">$1</span>=<span class=\"xval\">&quot;$2&quot;</span>"}, // "xml attribute value strings ..
{ rex:/(\xAB[\/]?)([-A-Za-z0-9_:]+)/g, tmplt:"$1<span class=\"xtag\">$2</span>"}, // "xml tag ..
{ rex:/\xAB/g, tmplt:"&lt;"}, // replace '«' by '<'
{ rex:/\xBB/g, tmplt:"&gt;"}, // replace '»' by '>'
];
Wiky.inverse.lang.js = [
{ rex:/<span class=\"?(cmt|kwd|mbr|obj|str)\"?>|<\/span>/mgi, tmplt:"" },
{ rex:/<strong>(.*?)<\/strong>/mgi, tmplt:"[*$1*]" },
"Wiky.inverse.code"
];
Wiky.inverse.lang.xml = [
{ rex:/<span class=\"?(cmt|xtag|xnam|xval)\"?>|<\/span>/mgi, tmplt:"" },
"Wiky.inverse.lang.js"
];
+374
View File
@@ -0,0 +1,374 @@
/* This work is licensed under Creative Commons GNU LGPL License.
License: http://creativecommons.org/licenses/LGPL/2.1/
Author: Stefan Goessner/2005-06
Web: http://goessner.net/
inspired by: http://xml-maiden.com/
*/
Wiky.rules.math = {
version: 0.95,
preshortcuts: [
// { rex:/[ ]/g, tmplt:"`"}, // omit due to charset support ie6
{ rex:/\+\-/g, tmplt:"&#177;"},
{ rex:/\/O|\\Oslash/g, tmplt:"&#216;"},
{ rex:/\/o|\\oslash/g, tmplt:"&#248;"},
{ rex:/<->|\\harr/g, tmplt:"&#8596;"},
{ rex:/<-|\\larr/g, tmplt:"&#8592;"},
{ rex:/->|\\rarr/g, tmplt:"&#8594;"},
{ rex:/<=>|\\hArr/g, tmplt:"&#8660;"},
{ rex:/=>|\\rArr/g, tmplt:"&#8658;"},
{ rex:/-=|\\equiv/g, tmplt:"&#8801;"},
{ rex:/<=|\\le/g, tmplt:"&#8804;"},
{ rex:/>=|\\ge/g, tmplt:"&#8805;"},
{ rex:/</g, tmplt:"&lt;"},
{ rex:/>/g, tmplt:"&gt;"}
],
postshortcuts: [
{ rex:/\*|\\middot/g, tmplt:"&#183;"},
{ rex:/\\x|\\times/g, tmplt:"&#215;"},
{ rex:/~=|\\cong/g, tmplt:"&#8773;"},
{ rex:/~~|\\asymp/g, tmplt:"&#8776;"},
{ rex:/~|\\sim/g, tmplt:"&#8764;"},
{ rex:/!=|\\neq|\\ne/g, tmplt:"&#8800;"},
{ rex:/\.\.\.|\\ldots/g, tmplt:"&#8230;"},
{ rex:/\\in|\\isin/g, tmplt:"&#8712;"},
{ rex:/([0-9])x([0-9])/g, tmplt:"$1&#215;$2"},
{ rex:/([A-Za-z]) x ([A-Za-z])/g, tmplt:"$1&#215;$2"},
// { rex:/[`]{4}/g, tmplt:"&#8195;"}, // omit due to charset support ie6
// { rex:/[`]{3}/g, tmplt:"&#8194;"},
// { rex:/[`]{2}/g, tmplt:" "},
// { rex:/[`]/g, tmplt:"&#8201;"},
{ rex:/\{/g, tmplt:"&#8206;"}, // unvisible left-to-right mark,
{ rex:/\}/g, tmplt:"&#8207;"} // unvisible right-to-left mark,
],
expr: [
{ rex:/\^\^/g, tmplt:"^&#94;"}, // ^ overindex
{ rex:/(\\sum|\\prod|\\int)_([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})\^([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<span class=\"o\"><span class=\"x\">$3</span>$1<span class=\"x\">$2</span></span>"}, // over-/underscript (\sum, \prod, \int)
{ rex:/(\\sum|\\prod|\\int)\^([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<span class=\"o\"><span class=\"x\">$2</span>$1<span>&#160;</span></span>"},
{ rex:/(\\sum|\\prod|\\int)_([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<span class=\"o\"><span>&#160;</span>$1<span class=\"x\">$2</span></span>"},
{ rex:/_([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})\^([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<span class=\"s\"><span class=\"i\">$2</span><span class=\"i\">$1</span></span>"}, // over-/underindex
{ rex:/\^([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<sup class=\"i\">$1</sup>"}, // overindex
{ rex:/_([-]?[a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<sub class=\"i\">$1</sub>"}, // underindex
{ rex:/-/g, tmplt:"&#8722;"},
{ rex:/([a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})\/([a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<span class=\"f\"><span class=\"n\">$1</span><span class=\"d\">$2</span></span>"}, // fraction
{ rex:/([a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})\/\/([a-zA-Z0-9\.&;#\\]+|\{@[0-9]+@\})/g, tmplt:"<sup>$1</sup>&#8260;<sub>$2</sub>"}, // fraction
{ rex:/\[((\[(([^,\]]+[,]){1,}[^\]]+)\][ \n]*){1,})\]/g, tmplt:function($0,$1){var m=Wiky.math.transpose($1.replace(/(^\[|\]$)/g,"").replace(/(\][ \n]*\[)/g,"|").split("|")),sz=" style=\"font-size:"+(m.len)+"00%;\"";/*alert("{("+m.mat.join(")}\n{(").split(",").join(")(")+")}");*/ return "<span class=\"lb\""+sz+">"+Wiky.math.fence()+"</span><span class=\"m\"><span class=\"e\">"+m.mat.join("</span></span>\n<span class=\"m\"><span class=\"e\">").split(",").join("</span><span class=\"e\">")+"</span></span><span class=\"rb\""+sz+">"+Wiky.math.fence()+"</span>";}}, // matrix
{ rex:/\[((?:[^,\]]){1,}[^\]]+)\]/g, tmplt:function($0,$1){var v=$1.split(","),sz=" style=\"font-size:"+v.length+"00%;\""; return "<span class=\"lb\""+sz+">"+Wiky.math.fence()+"</span><span class=\"v\"><span class=\"e\">"+v.join("</span><span class=\"e\">")+"</span></span><span class=\"rb\""+sz+">"+Wiky.math.fence()+"</span>";}}, // vector
{ rex:/!([a-zA-Z0-9\.&;]+)/g, tmplt:"<span class=\"b\">$1</span>" }, // bold vector symbol ..
{ rex:/\\prod/g, tmplt:"<span class=\"h\">&#8719;</span>"},
{ rex:/\\sum/g, tmplt:"<span class=\"h\">&#8721;</span>"},
{ rex:/\\int/g, tmplt:"<span class=\"h\">&#8747;</span>"},
"Wiky.rules.math.postshortcuts"
],
symbols: [
{ rex:/\\Alpha/g, tmplt:"&#913;"},
{ rex:/\\Beta/g, tmplt:"&#914;"},
{ rex:/\\Gamma/g, tmplt:"&#915;"},
{ rex:/\\Delta/g, tmplt:"&#916;"},
{ rex:/\\Epsilon/g, tmplt:"&#917;"},
{ rex:/\\Zeta/g, tmplt:"&#918;"},
{ rex:/\\Eta/g, tmplt:"&#919;"},
{ rex:/\\Theta/g, tmplt:"&#920;"},
{ rex:/\\Iota/g, tmplt:"&#921;"},
{ rex:/\\Kappa/g, tmplt:"&#922;"},
{ rex:/\\Lambda/g, tmplt:"&#923;"},
{ rex:/\\Mu/g, tmplt:"&#924;"},
{ rex:/\\Nu/g, tmplt:"&#925;"},
{ rex:/\\Xi/g, tmplt:"&#926;"},
{ rex:/\\Omicron/g, tmplt:"&#927;"},
{ rex:/\\Pi/g, tmplt:"&#928;"},
{ rex:/\\Rho/g, tmplt:"&#929;"},
{ rex:/\\Sigma/g, tmplt:"&#931;"},
{ rex:/\\Tau/g, tmplt:"&#932;"},
{ rex:/\\Upsilon/g, tmplt:"&#933;"},
{ rex:/\\Phi/g, tmplt:"&#934;"},
{ rex:/\\Chi/g, tmplt:"&#935;"},
{ rex:/\\Psi/g, tmplt:"&#936;"},
{ rex:/\\Omega/g, tmplt:"&#937;"},
{ rex:/\\alpha/g, tmplt:"&#945;"},
{ rex:/\\beta/g, tmplt:"&#946;"},
{ rex:/\\gamma/g, tmplt:"&#947;"},
{ rex:/\\delta/g, tmplt:"&#948;"},
{ rex:/\\epsilon/g, tmplt:"&#949;"},
{ rex:/\\zeta/g, tmplt:"&#950;"},
{ rex:/\\eta/g, tmplt:"&#951;"},
{ rex:/\\thetasym/g, tmplt:"&#977;"},
{ rex:/\\theta/g, tmplt:"&#952;"},
{ rex:/\\iota/g, tmplt:"&#953;"},
{ rex:/\\kappa/g, tmplt:"&#954;"},
{ rex:/\\lambda/g, tmplt:"&#955;"},
{ rex:/\\mu/g, tmplt:"&#956;"},
{ rex:/\\nu/g, tmplt:"&#957;"},
{ rex:/\\xi/g, tmplt:"&#958;"},
{ rex:/\\omicron/g, tmplt:"&#959;"},
{ rex:/\\piv/g, tmplt:"&#982;"},
{ rex:/\\pi/g, tmplt:"&#960;"},
{ rex:/\\rho/g, tmplt:"&#961;"},
{ rex:/\\sigmaf/g, tmplt:"&#962;"},
{ rex:/\\sigma/g, tmplt:"&#963;"},
{ rex:/\\tau/g, tmplt:"&#964;"},
{ rex:/\\upsilon/g, tmplt:"&#965;"},
{ rex:/\\phi/g, tmplt:"&#966;"},
{ rex:/\\chi/g, tmplt:"&#967;"},
{ rex:/\\psi/g, tmplt:"&#968;"},
{ rex:/\\omega/g, tmplt:"&#969;"},
{ rex:/\\upsih/g, tmplt:"&#978;"},
// miscellaneous symbols
{ rex:/\\bull/g, tmplt:"&#8226;"},
{ rex:/\\uarr/g, tmplt:"&#8593;"},
{ rex:/\\darr/g, tmplt:"&#8595;"},
{ rex:/\\crarr/g, tmplt:"&#8629;"},
{ rex:/\\lArr/g, tmplt:"&#8656;"},
{ rex:/\\uArr/g, tmplt:"&#8657;"},
{ rex:/\\dArr/g, tmplt:"&#8659;"},
{ rex:/\\forall/g, tmplt:"&#8704;"},
{ rex:/\\part/g, tmplt:"&#8706;"},
{ rex:/\\exist/g, tmplt:"&#8707;"},
{ rex:/\\empty/g, tmplt:"&#8709;"},
{ rex:/\\nabla/g, tmplt:"&#8711;"},
{ rex:/\\notin/g, tmplt:"&#8713;"},
{ rex:/\\ni/g, tmplt:"&#8715;"},
{ rex:/\\minus/g, tmplt:"&#8722;"},
{ rex:/\\lowast/g, tmplt:"&#8727;"},
{ rex:/\\sqrt|\\radic/g, tmplt:"&#8730;"},
{ rex:/\\prop/g, tmplt:"&#8733;"},
{ rex:/\\infin/g, tmplt:"&#8734;"},
{ rex:/\\ang/g, tmplt:"&#8736;"},
{ rex:/\\and/g, tmplt:"&#8743;"},
{ rex:/\\or/g, tmplt:"&#8744;"},
{ rex:/\\cap/g, tmplt:"&#8745;"},
{ rex:/\\cup/g, tmplt:"&#8746;"},
{ rex:/\\there4/g, tmplt:"&#8756;"},
{ rex:/\\sub/g, tmplt:"&#8834;"},
{ rex:/\\sup/g, tmplt:"&#8835;"},
{ rex:/\\nsub/g, tmplt:"&#8836;"},
{ rex:/\\sube/g, tmplt:"&#8838;"},
{ rex:/\\supe/g, tmplt:"&#8839;"},
{ rex:/\\oplus/g, tmplt:"&#8853;"},
{ rex:/\\otimes/g, tmplt:"&#8855;"},
{ rex:/\\perp/g, tmplt:"&#8869;"},
{ rex:/\\sdot/g, tmplt:"&#8901;"}
]
};
Wiky.inverse.math = {
pre: [
{ rex:/&#8722;|\u2212/g, tmplt:"-"},
{ rex:/&#8201;|\u2009/g, tmplt:"&#8201;"},
{ rex:/&#8206;|\u200E/g, tmplt:"{"},
{ rex:/&#8207;|\u200F/g, tmplt:"}"}
],
post: [
// { rex:/([$])/g, tmplt:"\\$1" },
{ rex:/&#94;|\x5E/g, tmplt:"^"},
{ rex:/&lt;/g, tmplt:"<"},
{ rex:/&gt;/g, tmplt:">"}
],
shortcuts: [
// { rex:/&#8195;|\u2003/g, tmplt:" "}, // omit due to charset support ie6
// { rex:/&#8194;|\u2002/g, tmplt:" "},
// { rex:/&#8201;|\u2009/g, tmplt:" "},
{ rex:/&#177;|\xB1/g, tmplt:"+-"},
{ rex:/&#183;|\xB7/g, tmplt:"*"},
{ rex:/&#215;|\xD7/g, tmplt:"\\x"},
{ rex:/&#216;|\xD8/g, tmplt:"/O"},
{ rex:/&#248;|\xF8/g, tmplt:"/o"},
{ rex:/&#8592;|\u2190/g, tmplt:"&lt;-"},
{ rex:/&#8594;|\u2192/g, tmplt:"-&gt;"},
{ rex:/&#8596;|\u2194/g, tmplt:"&lt;-&gt;"},
{ rex:/&#8658;|\u21D2/g, tmplt:"=&gt;"},
{ rex:/&#8660;|\u21D4/g, tmplt:"&lt;=&gt;"},
{ rex:/&#8764;|\u223C/g, tmplt:"~"},
{ rex:/&#8773;|\u2245/g, tmplt:"~="},
{ rex:/&#8776;|\u2248/g, tmplt:"~~"},
{ rex:/&#8800;|\u2260/g, tmplt:"!="},
{ rex:/&#8230;/g, tmplt:"..."},
{ rex:/&#8801;|\u2261/g, tmplt:"-="},
{ rex:/&#8804;|\u2264/g, tmplt:"&lt;="},
{ rex:/&#8805;|\u2265/g, tmplt:"&gt;="}
],
expr: [
{ rex:/<span class=\"s\"><span class=\"i\">(\{?@[0-9]+@\}?)<\/span><span class="i">(\{?@[0-9]+@\}?)<\/span><\/span>/g, tmplt:"_$2^$1"}, // superscript + subscript
{ rex:/<span class=\"o\"><span class=\"x\">(\{?@[0-9]+@\}?)<\/span>(\\prod|\\sum|\\int)<span class=\"x\">(\{?@[0-9]+@\}?)<\/span><\/span>/g, tmplt:"$2_$3^$1"}, // overscript + underscript
{ rex:/<span class=\"o\"><span>@[0-9]+@<\/span>(\\prod|\\sum|\\int)<span class=\"x\">(\{?@[0-9]+@\}?)<\/span><\/span>/mgi, tmplt:"$1_$2", dbg:true}, // underscript
{ rex:/<span class=\"o\"><span class=\"x\">(\{?@[0-9]+@\}?)<\/span>(\\prod|\\sum|\\int)<span>@[0-9]+@<\/span><\/span>/mgi, tmplt:"$2^$1"}, // overscript
{ rex:/<span class=\"f\"><span class=\"n\">(\{?@[0-9]+@\}?)<\/span><span class="d">(\{?@[0-9]+@\}?)<\/span><\/span>/mgi, tmplt:"$1/$2"}, // fraction
{ rex:/<span class=\"lb\"[^>]*>&[^;]+;<\/span><span class=\"v\">((?:<span class=\"e\">[^>]*<\/span>){2,})<\/span><span class=\"rb\"[^>]*>&[^;]+;<\/span>/mgi, tmplt:function($0,$1){return "["+$1.replace(/(?:^<span class=\"e\">|<\/span>$)/g,"").replace(/<\/span><span class=\"e\">/g,",")+"]";}}, // vector ..
{ rex:/<span class=\"lb\"[^>]*>&[^;]+;<\/span>((?:<span class=\"m\">(?:(?:<span class=\"e\">[^>]*<\/span>){2,})<\/span>[^>]*){2,})<span class=\"rb\"[^>]*>&[^;]+;<\/span>/mgi, tmplt:function($0,$1){return "[["+Wiky.math.transpose($1.replace(/(?:^<span class=\"m\"><span class=\"e\">|<\/span><\/span>$)/g,"").replace(/<\/span><span class=\"e\">/g,",").replace(/<\/span><\/span>[^>]*<span class=\"m\"><span class=\"e\">/g,"|").split("|")).mat.join("][")+"]]";}}, // matrix ..
{ rex:/<span class=\"b\">(@[0-9]+@)<\/span>/mgi, tmplt:"!$1"}, // bold vector ..
{ rex:/<sup>(\{?@[0-9]+@\}?)<\/sup>&#8260;<sub>(\{?@[0-9]+@\}?)<\/sub>/mgi, tmplt:"$1//$2"},
{ rex:/<sup class=\"i\">(\{?@[0-9]+@\}?)<\/sup>/mgi, tmplt:"^$1" },
{ rex:/<sub class=\"i\">(\{?@[0-9]+@\}?)<\/sub>/mgi, tmplt:"_$1" }
],
symbols: [
// greek symbols
{ rex:/&#913;|\u391/g, tmplt:"\\Alpha"},
{ rex:/&#914;|\u392/g, tmplt:"\\Beta"},
{ rex:/&#915;|\u393/g, tmplt:"\\Gamma"},
{ rex:/&#916;|\u394/g, tmplt:"\\Delta"},
{ rex:/&#917;|\u395/g, tmplt:"\\Epsilon"},
{ rex:/&#918;|\u396/g, tmplt:"\\Zeta"},
{ rex:/&#919;|\u397/g, tmplt:"\\Eta"},
{ rex:/&#920;|\u398/g, tmplt:"\\Theta"},
{ rex:/&#921;|\u399/g, tmplt:"\\Iota"},
{ rex:/&#922;|\u39A/g, tmplt:"\\Kappa"},
{ rex:/&#923;|\u39B/g, tmplt:"\\Lambda"},
{ rex:/&#924;|\u39C/g, tmplt:"\\Mu"},
{ rex:/&#925;|\u39D/g, tmplt:"\\Nu"},
{ rex:/&#926;|\u39E/g, tmplt:"\\Xi"},
{ rex:/&#927;|\u39F/g, tmplt:"\\Omicron"},
{ rex:/&#928;|\u3A0/g, tmplt:"\\Pi"},
{ rex:/&#929;|\u3A1/g, tmplt:"\\Rho"},
{ rex:/&#931;|\u3A3/g, tmplt:"\\Sigma"},
{ rex:/&#932;|\u3A4/g, tmplt:"\\Tau"},
{ rex:/&#933;|\u3A5/g, tmplt:"\\Upsilon"},
{ rex:/&#934;|\u3A6/g, tmplt:"\\Phi"},
{ rex:/&#935;|\u3A7/g, tmplt:"\\Chi"},
{ rex:/&#936;|\u3A8/g, tmplt:"\\Psi"},
{ rex:/&#937;|\u3A9/g, tmplt:"\\Omega"},
{ rex:/&#945;|\u3B1/g, tmplt:"\\alpha"},
{ rex:/&#946;|\u3B2/g, tmplt:"\\beta"},
{ rex:/&#947;|\u3B3/g, tmplt:"\\gamma"},
{ rex:/&#948;|\u3B4/g, tmplt:"\\delta"},
{ rex:/&#949;|\u3B5/g, tmplt:"\\epsilon"},
{ rex:/&#950;|\u3B6/g, tmplt:"\\zeta"},
{ rex:/&#951;|\u3B7/g, tmplt:"\\eta"},
{ rex:/&#977;|\u3D1/g, tmplt:"\\thetasym"},
{ rex:/&#952;|\u3B8/g, tmplt:"\\theta"},
{ rex:/&#953;|\u3B9/g, tmplt:"\\iota"},
{ rex:/&#954;|\u3BA/g, tmplt:"\\kappa"},
{ rex:/&#955;|\u3BB/g, tmplt:"\\lambda"},
{ rex:/&#956;|\u3BC/g, tmplt:"\\mu"},
{ rex:/&#957;|\u3BD/g, tmplt:"\\nu"},
{ rex:/&#958;|\u3BE/g, tmplt:"\\xi"},
{ rex:/&#959;|\u3BF/g, tmplt:"\\omicron"},
{ rex:/&#960;|\u3C0/g, tmplt:"\\pi"},
{ rex:/&#961;|\u3C1/g, tmplt:"\\rho"},
{ rex:/&#962;|\u3C2/g, tmplt:"\\sigmaf"},
{ rex:/&#963;|\u3C3/g, tmplt:"\\sigma"},
{ rex:/&#964;|\u3C4/g, tmplt:"\\tau"},
{ rex:/&#965;|\u3C5/g, tmplt:"\\upsilon"},
{ rex:/&#966;|\u3C6/g, tmplt:"\\phi"},
{ rex:/&#967;|\u3C7/g, tmplt:"\\chi"},
{ rex:/&#968;|\u3C8/g, tmplt:"\\psi"},
{ rex:/&#969;|\u3C9/g, tmplt:"\\omega"},
// miscellaneous symbols
{ rex:/&#978;|\u3D2/g, tmplt:"\\upsih"},
{ rex:/&#982;|\u3D6/g, tmplt:"\\piv"},
{ rex:/&#8226;|\u2022/g, tmplt:"\\bull"},
{ rex:/&#8593;|\u2191/g, tmplt:"\\uarr"},
{ rex:/&#8595;|\u2193/g, tmplt:"\\darr"},
{ rex:/&#8629;|\u21B5/g, tmplt:"\\crarr"},
{ rex:/&#8656;|\u21D0/g, tmplt:"\\lArr"},
{ rex:/&#8657;|\u21D1/g, tmplt:"\\uArr"},
{ rex:/&#8659;|\u21D3/g, tmplt:"\\dArr"},
{ rex:/&#8704;|\u2200/g, tmplt:"\\forall"},
{ rex:/&#8706;|\u2202/g, tmplt:"\\part"},
{ rex:/&#8707;|\u2203/g, tmplt:"\\exist"},
{ rex:/&#8709;|\u2205/g, tmplt:"\\empty"},
{ rex:/&#8711;|\u2207/g, tmplt:"\\nabla"},
{ rex:/&#8712;|\u2208/g, tmplt:"\\isin"},
{ rex:/&#8713;|\u2209/g, tmplt:"\\notin"},
{ rex:/&#8715;|\u220B/g, tmplt:"\\ni"},
{ rex:/<span class=\"h\">(&#8719;|\u220F)<\/span>/g, tmplt:"\\prod"},
{ rex:/<span class=\"h\">(&#8721;|\u2211)<\/span>/g, tmplt:"\\sum"},
{ rex:/&#8727;|\u2217/g, tmplt:"\\lowast"},
{ rex:/&#8730;|\u221A/g, tmplt:"\\sqrt"},
{ rex:/&#8733;|\u221D/g, tmplt:"\\prop"},
{ rex:/&#8734;|\u221E/g, tmplt:"\\infin"},
{ rex:/&#8736;|\u2220/g, tmplt:"\\ang"},
{ rex:/&#8743;|\u2227/g, tmplt:"\\and"},
{ rex:/&#8744;|\u2228/g, tmplt:"\\or"},
{ rex:/&#8745;|\u2229/g, tmplt:"\\cap"},
{ rex:/&#8746;|\u222A/g, tmplt:"\\cup"},
{ rex:/<span class=\"h\">(?:&#8747;|\u222B)<\/span>/g, tmplt:"\\int"},
{ rex:/&#8756;|\u2234/g, tmplt:"\\there4"},
{ rex:/&#8834;|\u2282/g, tmplt:"\\sub"},
{ rex:/&#8835;|\u2283/g, tmplt:"\\sup"},
{ rex:/&#8836;|\u2284/g, tmplt:"\\nsub"},
{ rex:/&#8838;|\u2286/g, tmplt:"\\sube"},
{ rex:/&#8839;|\u2287/g, tmplt:"\\supe"},
{ rex:/&#8853;|\u2295/g, tmplt:"\\oplus"},
{ rex:/&#8855;|\u2297/g, tmplt:"\\otimes"},
{ rex:/&#8869;|\u22A5/g, tmplt:"\\perp"},
{ rex:/&#8901;|\u22C5/g, tmplt:"\\sdot"}
]
};
Wiky.math = {
toHtml: function(str) {
var expr = function(itr) { // region from "{" to "}", nesting allowed ..
var s = "";
for (var c = itr.str.charAt(itr.pos++); itr.pos <= itr.str.length && c != "}"; c = itr.str.charAt(itr.pos++))
s += (c == "{") ? ("{"+expr(itr)+"}") : c;
return Wiky.store(Wiky.apply(s, Wiky.rules.math.expr));
};
str = Wiky.apply(str, Wiky.rules.math.preshortcuts);
str = Wiky.apply(str, Wiky.rules.math.symbols);
str = expr({str:str,pos:0});
return str;
},
toWiki: function(str) {
var parseTree = function(itr, endtag) {
var c, s="",gt,nam,idxof=function(s,c,p){var i=s.indexOf(c,p);return i>=0?i:s.length;}
for (itr.buf=itr.str.substr(itr.pos,endtag.length);
itr.pos<itr.str.length && (!endtag || itr.buf!=endtag);
itr.buf=itr.str.substr(++itr.pos,endtag.length)) {
if ((c=itr.str.charAt(itr.pos))=="<" && (gt=idxof(itr.str,">",itr.pos)) < idxof(itr.str,"/",itr.pos)) { // start tags .. no empty elements or endtags ..
nam = itr.str.substring(itr.pos+1,Math.min(idxof(itr.str," ",itr.pos),gt));
s += itr.str.substring(itr.pos,itr.pos=gt+1) + parseTree(itr, "</" + nam + ">") + "</" + nam + ">";
itr.pos += nam.length+3;
}
else
s += c;
}
itr.pos--;
return Wiky.store(s, true);
};
str = Wiky.apply(str, Wiky.inverse.math.pre);
str = Wiky.apply(str, Wiky.inverse.math.symbols);
str = parseTree({str:str,pos:0,buf:null}, "");
while (str.match(/@[0-9]+@/g) != null)
str = Wiky.apply(str.replace(/@([0-9]+)@/g, function($0,$1){return Wiky.restore($1);}), Wiky.inverse.math.expr);
str = Wiky.apply(str, Wiky.inverse.math.shortcuts);
str = Wiky.apply(str, Wiky.inverse.math.post);
return str;
},
fence: function(str) {
return window && window.ActiveXObject ? "&#160;" : "&#8201;";
},
transpose: function (m) {
var t=[];
for (var i in m) {
m[i] = m[i].split(",");
for (var j in m[i]) {
if (!t[j]) t[j]=[];
t[j][i] = m[i][j];
}
}
for (var i in t)
t[i] = t[i].join(",");
return {mat:t, len:m.length};
}
};
Wiky.rules.pre = Wiky.rules.pre.concat({ rex:/\\([$])/g, tmplt:function($0,$1){return Wiky.store($1);} });
Wiky.rules.nonwikiblocks = Wiky.rules.nonwikiblocks.concat(
[
{ rex:/\[\(([a-zA-Z0-9\.-]+)\)\$([^$]*)\$\]/g, tmplt:function($0,$1,$2){return ":p]<div class=\"eq\"><a name=\"eq"+$1+"\">("+$1+")</a>" + Wiky.math.toHtml($2) + "</div>[p:";} }, // numbered equation
{ rex:/\[\$([^$]*)\$\]/g, tmplt:function($0,$1){return ":p]<div class=\"eq\">" + Wiky.math.toHtml($1) + "</div>[p:";} }, // equation
]);
Wiky.rules.nonwikiinlines = Wiky.rules.nonwikiinlines.concat(
{ rex:/\$([^$]*)\$/g, tmplt:function($0,$1){return "<dfn>" + Wiky.math.toHtml($1) + "</dfn>";} } // inline equation
);
Wiky.inverse.pre = Wiky.inverse.pre.concat({ rex:/([\$])/g, tmplt:"\\$1" });
Wiky.inverse.nonwikiblocks = Wiky.inverse.nonwikiblocks.concat(
[
{ rex:/<div class=\"eq\"><a name=\"eq([0-9]+)\">(?:.*?)<\/a>(.*?)<\/div>/g, tmplt:function($0,$1,$2){return Wiky.store("[("+$1+")$"+Wiky.math.toWiki($2)+"$]");} }, // numbered equation
{ rex:/<div class=\"eq\">(.*?)<\/div>/g, tmplt:function($0,$1){return Wiky.store("[$"+Wiky.math.toWiki($1)+"$]");} }, // equation
]);
Wiky.inverse.nonwikiinlines = Wiky.inverse.nonwikiinlines.concat(
{ rex:/<dfn>(.*?)<\/dfn>/g, tmplt:function($0,$1){return Wiky.store("$"+Wiky.math.toWiki($1)+"$");} } // inline equation
);
+23
View File
@@ -0,0 +1,23 @@
/*
Extension rules for S3AjaxWiki
*/
Wiky.rules.wikiinlines = Wiky.rules.wikiinlines.concat(
{
rex: /([A-Z][a-z0-9]+(?:[A-Z][a-z0-9]*)+)/g,
tmplt: '<a class="wikiword" href="$1">$1</a>'
}
);
Wiky.inverse.wikiinlines = Wiky.inverse.wikiinlines.concat(
{
rex: /<a class="?wikiword"? [^>]*?>(.*?)<\/a>/mgi,
tmplt:"$1"
},
{
rex: /<a class="?newword"? [^>]*?>(.*?)<\/a>/mgi,
tmplt:"$1"
}
);