265 lines
6.2 KiB
JavaScript
265 lines
6.2 KiB
JavaScript
|
/**
|
||
|
* 2011 Peter 'Pita' Martischka
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
The Pad Module trys to simulate the pad object from EtherPad. You can find the original code in /etherpad/src/etherpad/pad/model.js
|
||
|
see https://github.com/ether/pad/blob/master/etherpad/src/etherpad/pad/model.js
|
||
|
*/
|
||
|
|
||
|
var Changeset = require("./Changeset");
|
||
|
var AttributePoolFactory = require("./AttributePoolFactory");
|
||
|
|
||
|
/**
|
||
|
* The initial Text of a Pad
|
||
|
*/
|
||
|
exports.startText = "Hello World\nGoodbye Etherpad";
|
||
|
|
||
|
/**
|
||
|
* A Array with all known Pads
|
||
|
*/
|
||
|
globalPads = [];
|
||
|
|
||
|
/**
|
||
|
* Return a Function Wrapper to work with the Pad
|
||
|
* @param id A String with the id of the pad
|
||
|
* @param createIfNotExist A Boolean which says the function if it should create the Pad if it not exist
|
||
|
*/
|
||
|
exports.getPad = function(id, createIfNotExist)
|
||
|
{
|
||
|
if(!globalPads[id] && createIfNotExist == true)
|
||
|
{
|
||
|
createPad(id);
|
||
|
}
|
||
|
|
||
|
if(!globalPads[id])
|
||
|
return null;
|
||
|
|
||
|
globalPads[id].timestamp = new Date().getTime();
|
||
|
|
||
|
var functionWrapper = {};
|
||
|
|
||
|
functionWrapper.id = id;
|
||
|
functionWrapper.appendRevision = function (theChangeset, author) {return appendRevision(id, theChangeset, author)};
|
||
|
functionWrapper.text = function () {return text(id)};
|
||
|
functionWrapper.atext = function () {return atext(id)};
|
||
|
functionWrapper.pool = function () {return pool(id)};
|
||
|
functionWrapper.getHeadRevisionNumber = function () {return getHeadRevisionNumber(id)};
|
||
|
functionWrapper.getRevisionChangeset = function (revNum) {return getRevisionChangeset(id, revNum)};
|
||
|
functionWrapper.getRevisionAuthor = function (revNum) {return getRevisionAuthor(id, revNum)};
|
||
|
functionWrapper.getAllAuthors = function () {return getAllAuthors(id)};
|
||
|
|
||
|
return functionWrapper;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ensures that the Pad exists
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
exports.ensurePadExists = function(id)
|
||
|
{
|
||
|
if(!globalPads[id])
|
||
|
{
|
||
|
createPad(id);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an empty pad
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function createPad(id)
|
||
|
{
|
||
|
var pad = {};
|
||
|
globalPads[id] = pad;
|
||
|
|
||
|
pad.id = id;
|
||
|
pad.rev = [];
|
||
|
pad.head = -1;
|
||
|
pad.atext = Changeset.makeAText("\n");
|
||
|
pad.apool = AttributePoolFactory.createAttributePool();
|
||
|
pad.authors = [];
|
||
|
|
||
|
var firstChangeset = Changeset.makeSplice("\n", 0, 0,
|
||
|
exports.cleanText(exports.startText));
|
||
|
appendRevision(id, firstChangeset, '');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Append a changeset to a pad
|
||
|
* @param id The Pad id
|
||
|
* @param theChangeset the changeset which should apply to the text
|
||
|
* @param The author of the revision, can be null
|
||
|
*/
|
||
|
function appendRevision(id, theChangeset, author)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
|
||
|
if(!author)
|
||
|
author = '';
|
||
|
|
||
|
var atext = globalPads[id].atext;
|
||
|
var apool = globalPads[id].apool;
|
||
|
var newAText = Changeset.applyToAText(theChangeset, atext, apool);
|
||
|
Changeset.copyAText(newAText, atext);
|
||
|
|
||
|
var newRev = ++globalPads[id].head;
|
||
|
globalPads[id].rev[newRev] = {};
|
||
|
globalPads[id].rev[newRev].changeset = theChangeset;
|
||
|
globalPads[id].rev[newRev].meta = {};
|
||
|
globalPads[id].rev[newRev].meta.author = author;
|
||
|
globalPads[id].rev[newRev].meta.timestamp = new Date().getTime();
|
||
|
|
||
|
//ex. getNumForAuthor
|
||
|
apool.putAttrib(['author',author||'']);
|
||
|
|
||
|
if(newRev%100==0)
|
||
|
{
|
||
|
globalPads[id].rev[newRev].meta.atext=atext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns all Authors of a Pad
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function getAllAuthors(id)
|
||
|
{
|
||
|
var authors = [];
|
||
|
|
||
|
for(key in globalPads[id].apool.numToAttrib)
|
||
|
{
|
||
|
if(globalPads[id].apool.numToAttrib[key][0] == "author" && globalPads[id].apool.numToAttrib[key][1] != "")
|
||
|
{
|
||
|
authors.push(globalPads[id].apool.numToAttrib[key][1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return authors;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the plain text of a pad
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
|
||
|
function text(id)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
|
||
|
return globalPads[id].atext.text;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the Attributed Text of a pad
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function atext(id)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
|
||
|
return globalPads[id].atext;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the Attribute Pool whichs the Pad is using
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function pool(id)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
|
||
|
return globalPads[id].apool;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the latest Revision Number of the Pad
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function getHeadRevisionNumber(id)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
|
||
|
return globalPads[id].head;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the changeset of a specific revision
|
||
|
* @param id The Pad id
|
||
|
* @param revNum The Revision Number
|
||
|
*/
|
||
|
function getRevisionChangeset(id, revNum)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
throwExceptionIfRevDontExist(id, revNum);
|
||
|
|
||
|
return globalPads[id].rev[revNum].changeset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the author of a specific revision
|
||
|
* @param id The Pad id
|
||
|
* @param revNum The Revision Number
|
||
|
*/
|
||
|
function getRevisionAuthor(id, revNum)
|
||
|
{
|
||
|
throwExceptionIfPadDontExist(id);
|
||
|
throwExceptionIfRevDontExist(id, revNum);
|
||
|
|
||
|
return globalPads[id].rev[revNum].meta.author;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the ID is a valid Pad ID and trows an Exeption if not
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function throwExceptionIfPadDontExist(id)
|
||
|
{
|
||
|
if(id == null)
|
||
|
{
|
||
|
throw "Padname is null!";
|
||
|
}
|
||
|
if(!globalPads[id])
|
||
|
{
|
||
|
throw "Pad don't exist!'";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the Revision of a Pad is valid and throws an Exeption if not
|
||
|
* @param id The Pad id
|
||
|
*/
|
||
|
function throwExceptionIfRevDontExist(id, revNum)
|
||
|
{
|
||
|
if(revNum == null)
|
||
|
throw "revNum is null";
|
||
|
|
||
|
if((typeof revNum) != "number")
|
||
|
throw revNum + " is no Number";
|
||
|
|
||
|
if(revNum < 0 || revNum > globalPads[id].head)
|
||
|
throw "The Revision " + revNum + " don't exist'";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copied from the Etherpad source code, don't know what its good for
|
||
|
* @param txt
|
||
|
*/
|
||
|
exports.cleanText = function (txt) {
|
||
|
return txt.replace(/\r\n/g,'\n').replace(/\r/g,'\n').replace(/\t/g, ' ').replace(/\xa0/g, ' ');
|
||
|
}
|
||
|
|
||
|
|