docpad-plugin-livereload
Version:
Automatically refreshes your website whenever a rengeration is performed
185 lines (163 loc) • 4.48 kB
text/coffeescript
# Export Plugin
module.exports = (BasePlugin) ->
# Define Plugin
class LivereloadPlugin extends BasePlugin
# Plugin configuration
name: 'livereload'
# Plugin configuration
# Only enable us on the development environment
config:
channel: '/docpad-livereload'
pathname: '/docpad-livereload'
enabled: false
getSocket: null
inject: true
generateBeforeBlock: null
generateAfterBlock: null
listenBlock: null
injectBlock: null
scriptBlock: null
styleBlock: null
socketOptions:
transformer: 'websockets'
parser: 'JSON'
environments:
development:
enabled: true
# Populate Collections
# Used to inject our scripts block with our socket generate listener
populateCollections: (opts) ->
# Prepare
docpad = @docpad
config = @getConfig()
# Blocks
generateBeforeBlock = config.generateBeforeBlock or """
if ( typeof document.getElementsByTagName !== 'undefined' ) {
document.getElementsByTagName('html')[0].className += ' wait';
}
"""
generateAfterBlock = config.generateAfterBlock or """
document.location.reload();
"""
listenBlock = config.listenBlock or """
/* Did we just livereload? */
var log = !!(localStorage && console && console.log && true);
if ( log && localStorage.getItem('#{config.channel}/reloaded') === 'yes' ) {
localStorage.removeItem('#{config.channel}/reloaded');
console.log('LiveReload completed at', new Date())
}
/* Listen for the regenerated event and perform a reload of the page when the event occurs */
var listen = function(){
var primus = new Primus('#{config.channel}');
primus.on('data', function(data){
if ( data && data.message ) {
if ( data.message === 'generateBefore' ) {
if ( log ) {
console.log('LiveReload started at', new Date());
}
#{generateBeforeBlock}
}
else if ( data.message === 'generateAfter' ) {
if ( log ) {
localStorage.setItem('#{config.channel}/reloaded', 'yes');
}
#{generateAfterBlock}
}
}
});
};
"""
injectBlock = config.injectBlock or """
/* Inject socket into our page */
var inject = function(){
var t = document.createElement('script');
t.type = 'text/javascript';
t.async = 'async';
t.src = '#{config.pathname}/primus.js';
t.onload = listen;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(t, s);
};
"""
scriptBlock = config.scriptBlock or
if config.inject
"""
(function(){
#{listenBlock}
#{injectBlock}
if ( typeof Primus !== 'undefined' ) {
listen();
} else {
inject();
}
})();
"""
else
"""
(function(){
#{listenBlock}
if ( typeof Primus !== 'undefined' ) {
listen();
}
})();
"""
styleBlock = config.styleBlock or """
html.wait {
cursor: wait !important;
opacity: 0;
transition: opacity 0.5s ease;
}
"""
# Script
docpad.getBlock('scripts').add(scriptBlock, {defer:false})
# Style
docpad.getBlock('styles').add(styleBlock)
# Chain
# Setup Extend
# Start our socket
serverExtend: (opts) ->
# Prepare
{serverHttp} = opts
plugin = @
docpad = @docpad
config = @getConfig()
# Configuration
extendr = require('extendr')
socketOptions = extendr.deep({}, config.socketOptions, {
pathname: config.pathname
})
# Get socket using custom method if set
if @socket
docpad.log('info', "LiveReload listening to custom socket on channel #{config.channel}")
else
# Create a socket using primus
Primus = require('primus')
# Log
docpad.log('info', "LiveReload listening to new socket on channel #{config.channel}")
# Chain
# Generate Before
generateBefore: ->
# Notify client
# Chain
# Generate After
generateAfter: ->
# Notify client
# Chain
# DocPad Destroy
docpadDestroy: ->
# Destroy the sockets
# Chain