Browse Source

Add event API with events willparse and parsed

pull/498/head
m93a 6 years ago
parent
commit
7c21e5ef60
  1. 98
      lib/index.js
  2. 89
      test/misc.js

98
lib/index.js

@ -13,6 +13,9 @@ var LinkifyIt = require('linkify-it');
var mdurl = require('mdurl');
var punycode = require('punycode');
/* global Symbol */
var EVENTS = typeof Symbol === 'function' ? Symbol('events') : '__events';
var config = {
'default': require('./presets/default'),
@ -341,6 +344,8 @@ function MarkdownIt(presetName, options) {
this.helpers = utils.assign({}, helpers);
this[EVENTS] = {};
this.options = {};
this.configure(presetName);
@ -520,8 +525,12 @@ MarkdownIt.prototype.parse = function (src, env) {
var state = new this.core.State(src, this, env);
this.dispatchEvent('willparse', { state: state });
this.core.process(state);
this.dispatchEvent('parsed', { state: state });
return state.tokens;
};
@ -555,10 +564,14 @@ MarkdownIt.prototype.render = function (src, env) {
**/
MarkdownIt.prototype.parseInline = function (src, env) {
var state = new this.core.State(src, this, env);
state.inlineMode = true;
this.dispatchEvent('willparse', { state: state });
this.core.process(state);
this.dispatchEvent('parsed', { state: state });
return state.tokens;
};
@ -578,4 +591,87 @@ MarkdownIt.prototype.renderInline = function (src, env) {
};
function Event(name, params) {
if (!(this instanceof Event)) {
return new Event(name, params);
}
if (typeof params === 'object') {
var keys = Object.getOwnPropertyNames(params);
for (var i = 0; i < keys.length; i++) {
this[keys[i]] = params[keys[i]];
}
}
this.name = name;
this.timeStamp = +(new Date());
}
/**
* MarkdownIt.addEventListener(event, fn)
* - event (String): event name
* - fn (Function): callback
*
* Registers an event listener. If the function is already subscribed
* to this event, does nothing. The callback function will recieve a
* single argument - the Event object which contains these properties:
* - timestamp: the value of Date.now()
* - name: name of the event
* - state: (where applicable) the parser's state object
*
* The available events are:
* - willparse
* - parsed
**/
MarkdownIt.prototype.addEventListener = function (event, fn) {
var callbackArray = this[EVENTS][event] = this[EVENTS][event] || [];
if (typeof fn !== 'function') {
throw new TypeError('Argument 2 must be a function.');
}
if (callbackArray.indexOf(fn) === -1) {
callbackArray.push(fn);
}
};
/**
* MarkdownIt.removeEventListener(event, fn)
* - event (String): event name
* - fn (Function): callback
*
* Unsubscribes the callback from the event. If the callback isn't
* subscribed, does nothing. See [[MarkdownIt.addEventListener]]
* for the list of available events.
**/
MarkdownIt.prototype.removeEventListener = function (event, callback) {
var callbackArray = this[EVENTS][event] = this[EVENTS][event] || [];
var index = callbackArray.indexOf(callback);
if (index !== -1) {
callbackArray.splice(index, 1);
}
};
/**
* MarkdownIt.dispatchEvent(event)
* - event (String): event name
* - params (Object): event parameters
*
* Call all the functions subscribed to this event.
* See [[MarkdownIt.addEventListener]] for the list of available events.
**/
MarkdownIt.prototype.dispatchEvent = function (event, params) {
var callbackArray = this[EVENTS][event] = this[EVENTS][event] || [];
var e = new Event(event, params);
for (var i = 0; i < callbackArray.length; i++) {
callbackArray[i](e);
}
};
module.exports = MarkdownIt;

89
test/misc.js

@ -154,6 +154,95 @@ describe('API', function () {
);
});
it('event-parse', function () {
var md = markdownit();
var firedPre = false;
var firedPost = false;
var subscribed = true;
function preBlock(e) {
assert.strictEqual(subscribed, true);
assert.strictEqual(e.name, 'willparse');
assert.approximately(e.timeStamp, Date.now(), 10);
assert.strictEqual(e.state.inlineMode, false);
assert.strictEqual(firedPre, false);
assert.strictEqual(firedPost, false);
firedPre = true;
}
function postBlock(e) {
assert.strictEqual(subscribed, true);
assert.strictEqual(e.name, 'parsed');
assert.approximately(e.timeStamp, Date.now(), 10);
assert.strictEqual(e.state.inlineMode, false);
assert.strictEqual(firedPre, true);
assert.strictEqual(firedPost, false);
firedPost = true;
}
function preInline(e) {
assert.strictEqual(subscribed, true);
assert.strictEqual(e.name, 'willparse');
assert.approximately(e.timeStamp, Date.now(), 10);
assert.strictEqual(e.state.inlineMode, true);
assert.strictEqual(firedPre, false);
assert.strictEqual(firedPost, false);
firedPre = true;
}
function postInline(e) {
assert.strictEqual(subscribed, true);
assert.strictEqual(e.name, 'parsed');
assert.approximately(e.timeStamp, Date.now(), 10);
assert.strictEqual(e.state.inlineMode, true);
assert.strictEqual(firedPre, true);
assert.strictEqual(firedPost, false);
firedPost = true;
}
md.addEventListener('willparse', preBlock);
md.addEventListener('willparse', preBlock); // double-adding does nothing
md.addEventListener('parsed', postBlock);
md.render('*a*');
assert.strictEqual(firedPre, true);
assert.strictEqual(firedPost, true);
md.removeEventListener('willparse', preBlock);
md.removeEventListener('willparse', preBlock); // double-removing does nothing
md.removeEventListener('parsed', postBlock);
firedPre = firedPost = false;
md.addEventListener('willparse', preInline);
md.addEventListener('parsed', postInline);
md.renderInline('*a*');
assert.strictEqual(firedPre, true);
assert.strictEqual(firedPost, true);
md.removeEventListener('willparse', preInline);
md.removeEventListener('parsed', postInline);
firedPre = firedPost = false;
md.render('*a*');
md.renderInline('*a*');
assert.strictEqual(firedPre, false);
assert.strictEqual(firedPost, false);
});
});

Loading…
Cancel
Save