revisionist.coffee | |
---|---|
Utility functionsHTML annotated Diff function | htmlDiff = require('./lib/diff') |
Extend function | extend = require('./lib/extend.coffee') |
The Revisionist ClassThe main public Class. When you create an instance of Revisionist, this is the public API you get back. | class Revisionist |
The plugin registry | _plugins = {} |
The store registry | _stores = {} |
The version pointer | _currentVersion = 0 |
The internal store | _store = null |
Helper function for getting the previous version of the current one. | _getPreviousVersion = ->
version = _currentVersion - 1
if version < 0
version = 0
return version |
This class method lets you register a new plugin. | @registerPlugin: (namespace, Plugin) -> |
Do not register the plugin if one with the same namespace already exists | if _plugins[namespace]?
throw new Error("There's already a plugin in this namespace")
_plugins[namespace] = Plugin |
This class method unregisters an existing plugin | @unregisterPlugin: (namespace) ->
_plugins[namespace] = null |
This class method lets you register a new store | @registerStore: (namespace, Store) -> |
Do not register the store if one with the same namespace already exists | if _stores[namespace]?
throw new Error("There's already a store in this namespace")
_stores[namespace] = Store |
This class method unregisters an existing store | @unregisterStore: (namespace) ->
_stores[namespace] = null |
The default options: versions: The maximum number of versions you wish to store. The default is 10. plugin: The plugin you wish to use. The default is "simple" | defaults:
versions: 10
plugin: 'simple'
store: 'simple' |
The main constructor function that gets called when Revisionist is instantiated. | constructor: (options) -> |
Configures options | @options = {}
extend @options, @defaults
extend @options, options |
Configure store | @setStore(@options.store) |
Implements a getter for _currentVersion | getLatestVersionNumber: ->
_currentVersion-1 |
Sets the internal store | setStore: (store) -> |
Bail if the chosen store is not available in the store registry | Store = _stores[store]
unless Store?
throw new Error("The Store '#{store}' is not available!") |
Construct the Store | _store = new Store(@options) |
Adds a new revision for this instance. | update: (newValue) -> |
Check if the plugin is available | plugin = _plugins[@options.plugin]
unless plugin?.update?
throw new Error("Plugin #{@options.plugin} is not available!") |
Call the plugin's "update" function and get it's return value for storing. | newValue = plugin.update.call(plugin, newValue) |
Bump the current version number | _currentVersion += 1 |
Save the new version | _store.set(newValue, _currentVersion) |
Keep the internal cache trimmed according to the "versions" option. | if _currentVersion > @options.versions |
Remove the oldest version | _store.remove(0) |
Keep the _currentVersion pointer | _currentVersion = _store.size()
return newValue |
Recovers a specific revision from the cache | recover: (version, callback) -> |
Check if the plugin is available | plugin = _plugins[@options.plugin]
unless plugin?.recover?
throw new Error("Plugin #{@options.plugin} is not available!") |
Defaults to the current version - 1 | unless version?
version = _getPreviousVersion() |
Throw errors if the version is out of bounds | if version < 0
throw new Error("Version needs to be a positive number")
if version > _store.size()
throw new Error("This version doesn't exist") |
Call the plugin's "recover" function and return it's return value. plugin.recover.call(plugin, _store.get(version)) | |
Call the plugin's "recover" function and return it using the callback | if typeof callback is 'function'
_store.get(version, (data) -> |
Pipe the data through from the plugin to the callback | callback(plugin.recover.call(plugin, data))
) |
Represents the difference between two versions. | diff: (v1, v2, callback) -> |
If no v1 is passed in, the current version is assumed | unless v1?
v1 = _currentVersion - 1
v1 = 0 if v1 < 0 |
If no v2 is passed in, v1 - 1 is assumed. | unless v2?
v2 = v1 - 1
v2 = 0 if v2 < 0 |
Figure out which one is the old value and the new value | min = Math.min(v1, v2)
max = Math.max(v1, v2) |
Returns the diff hash | if typeof callback is 'function'
_store.get(min, (old) ->
_store.get(max, (n) ->
callback {old: old, new: n}
)
)
visualDiff: (v1, v2, callback) -> |
Pipes diff() into the htmlDiff() module | @diff(v1, v2, (diff) -> |
Bail out if both versions are not Strings | unless typeof diff.old is 'string' and typeof diff.new is 'string'
throw new Error('The content types of both versions must match')
callback( htmlDiff(diff.old, diff.new) )
) |
Clears the cache | clear: -> |
Reset the store | _store.clear() |
Reset the version pointer | _currentVersion = 0 |
Chain 'this' through | return @ |
Simple Plugin, a reference implementation of a Revisionist plugin | SimplePlugin = require('./plugins/simple.coffee') |
Registers SimplePlugin | Revisionist.registerPlugin('simple', SimplePlugin) |
Simple Store, a reference implementation of a Revisionist Store | SimpleStore = require('./stores/simple.coffee') |
Registers SimpleStore | Revisionist.registerStore('simple', SimpleStore)
module.exports = Revisionist
|