Stackedit/doc/developer-guide.md
2013-11-23 10:59:55 -08:00

16 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
      heroku rename 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 an other address, you have to add specific keys at the end of constants.js and eventually to set up specific proxies with the corresponding key/secret pairs (WordPress Proxy, Tumblr Proxy and Gatekeeper).

Architecture

Architecture diagram

The modules are loaded in the following order:

  1. The 3rd party libraries (jQuery, underscore.js...)
  2. The Extension objects
  3. The EventMgr module
  4. The core module
  5. The fileMgr module and the helpers modules
  6. The provider modules
  7. The publisher and synchronizer modules

This is important to emphasize 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 callback 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 to false when the network is recovered.


fileMgr

The fileMgr module is responsible for:

  • creating and deleting local files,
  • switching from one file to another.

Attributes:

Methods:

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 associated syncAttributes objects with their syncIndex as a key.
  • publishLocations: a map containing all the associated publishAttributes objects with their publishIndex as a key.

And the following methods:

  • addSyncLocation(syncAttributes): associates a syncAttributes object with the file.
  • removeSyncLocation(syncAttributes): unassociates a syncAttributes object with the file.
  • addPublishLocation(publishAttributes): associates a publishAttributes object with the file.
  • removePublishLocation(publishAttributes): unassociates a publishAttributes 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: the provider 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 new publishAttributes 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: the provider 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 in StackEdit. The following functions of the eventMgr module will trigger events of the same name. Extensions can listen to these events by implementing functions with the same name. The function addListener(eventName, callback) of the eventMgr module can be used by any other module to listen to these events.

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 are 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. Each extension that has configuration inputs in the settings dialog has to implement a listener for this event.

    Triggered by the core module. Only Extension objects can handle this event.

  • onSaveSettings(newConfig, event)

    A hook that is called when the settings dialog has to be validated. Each extension that has configuration is 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. Only Extension objects can handle this event.

  • onInit()

    A hook allowing enabled extensions to initialize.

    Triggered by the eventMgr module. Only Extension objects can handle this event.

    This event is triggered before onReady event and just after the config and enabled extensions properties have been set by the eventMgr.

Module injection

  • onFileMgrCreated(fileMgr)

    The fileMgr module has been created.

    • fileMgr: the fileMgr module.

    Triggered by the fileMgr module.

  • onSynchronizerCreated(synchronizer)

    The synchronizer module has been created.

    • synchronizer: the synchronizer module.

    Triggered by the synchronizer module.

  • onPublisherCreated(publisher)

    The publisher module has been created.

    • publisher: the publisher module.

    Triggered by the publisher module.

  • onEventMgrCreated()

    The eventMgr module has been created.

    • eventMgr: the eventMgr module.

    Triggered by the eventMgr module.

Operations on files

  • onFileCreated(fileDesc)

    A FileDescriptor object has been created.

    Triggered by the fileMgr module.

  • onFileDeleted(fileDesc)

    A FileDescriptor object has been removed from the fileSystem module.

    Triggered by the fileMgr module.

  • onFileSelected(fileDesc)

    A FileDescriptor object has been selected.

    Triggered by the fileMgr module. This event is triggered before onFileClosed (if another document is open) and onFileOpen events.

  • onFileClosed(fileDesc)

    The current FileDescriptor object is about to be detached from the editor.

    Triggered by the fileMgr module. This event is triggered after onFileSelected event and before onFileClosed event.

  • onFileOpen(fileDesc)

    The selected FileDescriptor object has been attached to the editor.

    Triggered by the fileMgr module. This event is triggered after onFileSelected and onFileClosed (if another document is open) events.

  • onContentChanged(fileDesc)

    The content of a FileDescriptor object has been modified.

  • onTitleChanged(fileDesc)

    The content of a FileDescriptor object has been modified.

Operations on folders

  • onFoldersChanged()

    The folders structure has changed.

Sync events

  • onSyncRunning()

    A synchronization job has just started or stopped.

    • isRunning: true if started, false if stopped.

    Triggered by the synchronizer module.

  • onSyncSuccess()

    A synchronization job has successfully finished.

    Triggered by the synchronizer module.

  • onSyncImportSuccess(fileDescList, provider)

    The import of documents has successfully finished.

    • fileDescList: the list of FileDescriptor objects that have been created.
    • provider: the provider module that handled the import.

    Triggered by the provider module that handled the import.

  • onSyncExportSuccess(fileDesc, syncAttributes)

    The export of one document has successfully finished.

    • fileDesc: the FileDescriptor object that has been exported.
    • syncAttributes: the descriptor object of new sync location.

    Triggered by the synchronizer module.

  • onSyncRemoved(fileDesc, syncAttributes)

    A sync location has been removed from a FileDescriptor object.

    • fileDesc: the FileDescriptor object.
    • syncAttributes: the descriptor object of the removed sync location.

Publish events

  • onPublishRunning()
  • onPublishSuccess()
  • onNewPublishSuccess()
  • onPublishRemoved()

Operations on Layout

  • onLayoutConfigure()
  • onLayoutCreated()
  • onLayoutResize()
  • onCreateButton()
  • onCreateEditorButton()
  • onCreatePreviewButton()

Operations on PageDown

  • onPagedownConfigure()
  • onSectionsCreated()
  • onMarkdownTrim()

Operation on ACE

  • onAceCreated()

Written with StackEdit.