21 KiB
Developer guide
Getting started
Pre-requisites
Before debugging
-
Download development tools:
npm install
-
Download dependencies:
bower install
-
Serve StackEdit at
http://localhost/
:(export PORT=80 && node server.js)
-
Run Chrome without application cache:
chrome --disable-application-cache
-
Run StackEdit in debug mode (serve original files instead of minified):
http://localhost/?debug
Add new dependencies
NOTE: StackEdit uses RequireJS for asynchronous module definition (AMD).
-
Install new dependencies using Bower:
bower install <library> --save
-
Add the new dependency to RequireJS configuration file (
main.js
):grunt bower
Build/minify
grunt
Deploy
-
on Heroku:
heroku create my-stackedit-instance git push heroku master
-
in a Docker container:
docker build -t my-stackedit-image . docker run -p 3000 my-stackedit-image
NOTE: OAuth authorizations work out of the box for address
http://localhost/
except for WordPress. To allow another address, you have to add specific keys at the end ofconstants.js
and eventually to set up specific proxies with the corresponding key/secret pairs (WordPress Proxy, Tumblr Proxy and Gatekeeper).
Architecture
The modules are loaded by RequireJS in the following order:
- The 3rd party libraries (jQuery, underscore.js...)
- The
Extension
modules - The
eventMgr
module - The
core
module - The
fileMgr
module and the helpers modules - The
Provider
modules - The
publisher
andsynchronizer
modules
This is important to notice in order to avoid circular dependencies. For instance, if an Extension
is declared with the core
module as a dependency, RequireJS will inject undefined
instead of the actual module.
Any module though can access any dependencies by implementing the proper injection listener provided by the eventMgr
.
core
The core
module is responsible for:
- creating the UI Layout, the ACE editor and the PageDown editor,
- loading/saving the settings,
- running periodic tasks,
- detecting the user activity,
- checking the offline status.
Attributes:
isOffline
: indicates the offline status of the application.
Methods:
onReady(callback)
: sets a callback to be called when all modules have been loaded and the DOM is ready.
NOTE: This is preferred over jQuery's
.ready()
because it ensures that all AMD modules are loaded by RequireJS.
runPeriodically(callback)
: sets a callback to be called every second.
NOTE: The callback will not run if the user is inactive or in StackEdit Viewer. User is considered inactive after 5 minutes of inactivity (mouse or keyboard).
setOffline()
: can be called by any other modules when a network timeout occurs for instance.
NOTE: the offline status is also set by detecting the window
offline
event.core.isOffline
is automatically set tofalse
when the network is recovered.
initEditor(fileDesc)
: creates or refreshes the PageDown editor with a givenFileDescriptor
object.
fileMgr
The fileMgr
module is responsible for:
- creating and deleting local files,
- switching from one file to another.
Attributes:
currentFile
: theFileDescriptor
object that is currently edited.
Methods:
createFile(title, content)
: creates aFileDescriptor
object, add it in thefileSystem
map and returns it.deleteFile(fileDesc)
: deletes aFileDescriptor
object from thefileSystem
map.selectFile(fileDesc)
: selects aFileDescriptor
object for editing.
FileDescriptor
The FileDescriptor
class represents a local file. A FileDescriptor
object has the following properties:
fileIndex
: the unique string index of the file in the file system.title
: the title of the document.content
: the content of the document.syncLocations
: a map containing all the associatedsyncAttributes
objects with theirsyncIndex
as a key.publishLocations
: a map containing all the associatedpublishAttributes
objects with theirpublishIndex
as a key.
And the following methods:
addSyncLocation(syncAttributes)
: associates asyncAttributes
object with the file.removeSyncLocation(syncAttributes)
: unassociates asyncAttributes
object with the file.addPublishLocation(publishAttributes)
: associates apublishAttributes
object with the file.removePublishLocation(publishAttributes)
: unassociates apublishAttributes
object with the file.
fileSystem
The fileSystem
module is a map containing all the FileDescriptor
objects with their fileIndex
as a key.
synchronizer
The synchronizer
module is responsible for:
- creating a new local file from a sync location (import).
- creating a new sync location from a local file (export).
- running 2 ways synchronization (upload and download) for all sync locations.
synchronizer's providers
A provider
module can be associated with the synchronizer
module if it implements the following functions:
importFiles()
: downloads one or multiple files and create local files associated with the sync locations.exportFile()
: uploads a local file to a new sync location.syncDown()
: performs a download of all the changes operated on all sync locations.syncUp()
: performs an upload of a change to a sync location.
syncAttributes
A syncAttributes
object is an object that describes a sync location. Attributes differ from one provider to another except for the following:
syncIndex
: the unique string index of the publish location.provider
: theprovider
module that handles the sync location.
publisher
The publisher
module is responsible for:
- creating new publish locations,
- updating existing publish locations.
publisher's providers
A provider
module can be associated with the publisher
module if it implements the following functions:
newPublishAttributes()
: returns a newpublishAttributes
object in order to create a new publish location.publish()
: performs publishing of one publish location.
publishAttributes
A publishAttributes
object is an object that describes a publish location. Attributes differ from one provider to another except for the following:
publishIndex
: the unique string index of the publish location.provider
: theprovider
module that handles the publish location.format
: the publishing format for the publish location. It can be:markdown
for Markdown format.html
for HTML format.template
for template format.
eventMgr
The eventMgr
module is responsible for receiving and dispatching events. Below is the list of all events signatures.
Most events (those that are not triggered by the eventMgr
module) can be triggered by calling methods of the same name in the eventMgr
module. For example:
eventMgr.onMessage('StackEdit is awesome!');
The method addListener(eventName, callback)
of the eventMgr
module can be used to listen to these events (except those that can only be handled by Extension
modules). For example:
eventMgr.addListener('onMessage', function(message) {
alert(message);
});
Extension
modules have the possibility to listen to those events by implementing methods of the same name. For example:
myExtension.onMessage = function(message) {
alert(message);
};
Core events
-
onReady()
All the modules are loaded and the DOM is ready.
Triggered by the
core
module.This is preferred over jQuery's
.ready()
because it ensures that all modules have been loaded by RequireJS. -
onMessage(message)
A message destined to the user has been produced.
message
: the text string of the message.
-
onError(error)
An error has been thrown.
error
: an error object or a string.
-
onOfflineChanged(isOffline)
The off-line status has changed.
isOffline
: the off-line status.
Triggered by the
core
module. -
onUserActive()
The user has just moved the mouse or pressed the keyboard.
Triggered by the
core
module. -
onAsyncRunning(isRunning)
Some asynchronous tasks have just started or stopped.
isRunning
: true if started, false if stopped.
Triggered by the
AsyncTask
module. -
onPeriodicRun()
A hook that is called periodically (every 1 second if user is active).
Triggered by the
core
module. -
onLoadSettings()
A hook that is called when the settings dialog has to be refreshed. Every
Extension
module that has configuration inputs in the settings dialog has to implement a listener for this event.Triggered by the
core
module. OnlyExtension
modules can handle this event. -
onSaveSettings(newConfig, event)
A hook that is called when the settings dialog has to be validated. Every
Extension
module that has configuration inputs in the settings dialog has to implement a listener for this event.newConfig
: the new configuration object, deduced from the settings dialog inputs.event
: the submit event object.stopPropagation
has to be called in case of an error when parsing settings dialog inputs.
Triggered by the
core
module. OnlyExtension
modules can handle this event. -
onInit()
A hook allowing enabled extensions to initialize.
Triggered by the
eventMgr
module. OnlyExtension
modules can handle this event.This event is triggered before
onReady
event and just after theconfig
andenabled
extensions properties have been set by theeventMgr
.
Module injection events
-
onFileMgrCreated(fileMgr)
The
fileMgr
module has been created.fileMgr
: thefileMgr
module.
Triggered by the
fileMgr
module. -
onSynchronizerCreated(synchronizer)
The
synchronizer
module has been created.synchronizer
: thesynchronizer
module.
Triggered by the
synchronizer
module. -
onPublisherCreated(publisher)
The
publisher
module has been created.publisher
: thepublisher
module.
Triggered by the
publisher
module. -
onEventMgrCreated()
The
eventMgr
module has been created.eventMgr
: theeventMgr
module.
Triggered by the
eventMgr
module.
file operation events
-
onFileCreated(fileDesc)
A
FileDescriptor
object has been created.fileDesc
: theFileDescriptor
object.
Triggered by the
fileMgr
module. -
onFileDeleted(fileDesc)
A
FileDescriptor
object has been removed from thefileSystem
module.fileDesc
: theFileDescriptor
object.
Triggered by the
fileMgr
module. -
onFileSelected(fileDesc)
A
FileDescriptor
object has been selected.fileDesc
: theFileDescriptor
object.
Triggered by the
fileMgr
module. This event is triggered beforeonFileClosed
(if another document is open) andonFileOpen
events. -
onFileClosed(fileDesc)
The current
FileDescriptor
object is about to be detached from the editor.fileDesc
: theFileDescriptor
object.
Triggered by the
fileMgr
module. This event is triggered afteronFileSelected
event and beforeonFileClosed
event. -
onFileOpen(fileDesc)
The selected
FileDescriptor
object has been attached to the editor.fileDesc
: theFileDescriptor
object.
Triggered by the
fileMgr
module. This event is triggered afteronFileSelected
andonFileClosed
(if another document is open) events. -
onContentChanged(fileDesc)
The content of a
FileDescriptor
object has been modified.fileDesc
: theFileDescriptor
object.
-
onTitleChanged(fileDesc)
The content of a
FileDescriptor
object has been modified.fileDesc
: theFileDescriptor
object.
-
onFoldersChanged()
The folders structure has changed.
Sync events
-
onSyncRunning(isRunning)
A synchronization job has just started or stopped.
isRunning
: true if started, false if stopped.
Triggered by the
synchronizer
module.A synchronization job is the action to download and upload all detected changes for all sync locations of all documents.
-
onSyncSuccess()
A synchronization job has successfully finished.
Triggered by the
synchronizer
module.A synchronization job is the action to download and upload all detected changes for all sync locations of all documents.
-
onSyncImportSuccess(fileDescList, provider)
The import of documents has successfully finished.
fileDescList
: the list ofFileDescriptor
objects that have been created.provider
: theprovider
module that handled the import.
Triggered by the
provider
module that handled the import.An import is the action to download multiple files and to create, for each, one
FileDescriptor
objects with one sync location. -
onSyncExportSuccess(fileDesc, syncAttributes)
The export of one document has successfully finished.
fileDesc
: theFileDescriptor
object that has been exported.syncAttributes
: the descriptor object of the new sync location.
Triggered by the
synchronizer
module.An export is the action to upload one file and to create one new sync location associated with one existing
FileDescriptor
]55 object. -
onSyncRemoved(fileDesc, syncAttributes)
A sync location has been removed from a
FileDescriptor
object.fileDesc
: theFileDescriptor
object.syncAttributes
: the descriptor object of the removed sync location.
Publish events
-
onPublishRunning(isRunning)
A document publication job has just started or stopped.
isRunning
: true if started, false if stopped.
Triggered by the
publisher
module.A publication job is the action to upload changes on multiple publish locations associated with one
FileDescriptor
]55 object. -
onPublishSuccess(fileDesc)
A document publication job has successfully finished.
fileDesc
: theFileDescriptor
object that has been published.
Triggered by the
publisher
module.A publication job is the action to upload changes on multiple publish locations associated with one
FileDescriptor
]55 object. -
onNewPublishSuccess(fileDesc, publishAttributes)
A new publish location has been successfully created.
fileDesc
: theFileDescriptor
object that has been published.publishAttributes
: the descriptor object of the new publish location.
Triggered by the
publisher
module. -
onPublishRemoved(fileDesc, publishAttributes)
A publish location has been removed from a
FileDescriptor
object.fileDesc
: theFileDescriptor
object.publishAttributes
: the descriptor object of the removed publish location.
Triggered by the
publisher
module.
UI Layout events
-
onLayoutConfigure(layoutConfig)
The layout is about to be configured.
layoutConfig
: the configuration object of the UI Layout library.
Triggered by the
core
module. -
onLayoutCreated(layout)
The layout has just been created.
layout
: the layout object of the UI Layout library.
Triggered by the
core
module. -
onLayoutResize(paneName)
One pane of the layout has been resized.
paneName
: the name of the resized layout pane.
Triggered by the
core
module. -
onCreateButton()
Allows extensions to add their own buttons in the navigation bar. Implemented listeners have to return an HTML button element. For example:
myExtension.onCreateButton = function() { var button = $('<button class="btn btn-success"><i class="icon-rocket"></i></button>'); button.click(function() { eventMgr.onMessage('Booom!'); }); return button[0]; };
Triggered by the
eventMgr
module. OnlyExtension
modules can handle this event. -
onCreateEditorButton()
Allows extensions to add their own buttons in the side bar. Implemented listeners have to return an HTML button element. See
onCreateButton
for a concrete example.Triggered by the
eventMgr
module. OnlyExtension
modules can handle this event. -
onCreatePreviewButton()
Allows extensions to add their own buttons over the preview. Implemented listeners have to return an HTML button element. See
onCreateButton
for a concrete example.Triggered by the
eventMgr
module. OnlyExtension
modules can handle this event.
PageDown events
-
onPagedownConfigure(editor)
The Pagedown editor is about to be created.
editor
: the Pagedown editor object beforerun
has been called.
Triggered by the
core
module. -
onAsyncPreview(callback)
Called after Pagedown's synchronous rendering to trigger extra asynchronous rendering (such as MathJax). Implemented listeners have to call the callback parameter after processing in order other
onAsyncPreview
listeners to run.callback
: the callback to call at the end of the asynchronous processing.
Triggered by the
eventMgr
module. OnlyExtension
modules can handle this event. -
onPreviewFinished(html)
Called after every
onAsyncPreview
listeners have been called.html
: the finally rendered HTML.
-
onSectionsCreated(sectionList)
The Markdown has been split into sections before rendering.
sectionList
: the list of section objects. Each section object contains:text
: the markdown substring contained in the section.textWithDelimiter
: the text with an added delimiter.
Triggered by the
markdownSectionParser
extension. -
onMarkdownTrim(offset)
The Markdown has been left trimmed by a certain number of character.
offset
: the number of characters that have been removed.
Triggered by the
yamlFrontMatterParser
extension.
ACE events
-
onAceCreated(aceEditor)
The ACE editor has just been created.
aceEditor
: the ACE editor object.
Triggered by the
core
module.
Written with StackEdit.