mirror of
https://github.com/astefanutti/decktape.git
synced 2024-12-02 06:35:51 +03:00
Migrate the generic plugin to Puppeteer API
This commit is contained in:
parent
23d832a70f
commit
0e50ee39df
@ -1,26 +1,27 @@
|
||||
// The generic plugin emulates end-user interaction by pressing keyboard and detects changes to the DOM.
|
||||
// The deck is considered over when no change is detected afterward.
|
||||
// The generic plugin emulates end-user interaction by pressing keyboard
|
||||
// and detects changes to the DOM. The deck is considered over when no change
|
||||
// is detected afterward.
|
||||
|
||||
exports.options = {
|
||||
keycode: {
|
||||
default: 'Right',
|
||||
metavar: '<code>',
|
||||
help: 'Key code pressed to navigate to next slide'
|
||||
key : {
|
||||
default : 'ArrowRight',
|
||||
metavar : '<key>',
|
||||
help : 'Key pressed to navigate to next slide'
|
||||
},
|
||||
maxSlides: {
|
||||
full: 'max-slides',
|
||||
metavar: '<size>',
|
||||
help: 'Maximum number of slides to export'
|
||||
maxSlides : {
|
||||
full : 'max-slides',
|
||||
metavar : '<size>',
|
||||
help : 'Maximum number of slides to export'
|
||||
}
|
||||
};
|
||||
|
||||
exports.help =
|
||||
'Emulates the end-user interaction by pressing the key with the specified --keycode option\n' +
|
||||
'and iterates over the presentation as long as:\n' +
|
||||
'- Any change to the DOM is detected by observing mutation events targeting the body element\n' +
|
||||
' and its subtree,\n' +
|
||||
'- Nor the number of slides exported has reached the specified --max-slides option.\n' +
|
||||
'The --keycode option must be one of the PhantomJS page event keys and defaults to [Right].';
|
||||
`Emulates the end-user interaction by pressing the key with the specified --key option
|
||||
and iterates over the presentation as long as:
|
||||
- Any change to the DOM is detected by observing mutation events targeting the body element
|
||||
and its subtree,
|
||||
- Nor the number of slides exported has reached the specified --max-slides option.
|
||||
The --key option must be one of the 'KeyboardEvent' keys and defaults to [${exports.options.key.default}].`;
|
||||
|
||||
exports.create = function (page, options) {
|
||||
return new Generic(page, options);
|
||||
@ -30,7 +31,7 @@ function Generic(page, options) {
|
||||
this.page = page;
|
||||
this.options = options;
|
||||
this.isNextSlideDetected = false;
|
||||
this.keycode = this.page.event.key[this.options.keycode || exports.options.keycode.default];
|
||||
this.key = this.options.key || exports.options.key.default;
|
||||
}
|
||||
|
||||
Generic.prototype = {
|
||||
@ -43,50 +44,36 @@ Generic.prototype = {
|
||||
return true;
|
||||
},
|
||||
|
||||
configure: function () {
|
||||
this.page.evaluate(function () {
|
||||
var observer = new window.MutationObserver(function () {
|
||||
window.callPhantom({ isNextSlideDetected: true });
|
||||
});
|
||||
observer.observe(document.querySelector('body'), { attributes: true, childList: true, subtree: true });
|
||||
});
|
||||
var plugin = this;
|
||||
this.page.onCallback = function (mutation) {
|
||||
if (mutation.isNextSlideDetected)
|
||||
plugin.isNextSlideDetected = true;
|
||||
};
|
||||
configure: async function () {
|
||||
await this.page.exposeFunction('onMutation', _ => this.isNextSlideDetected = true);
|
||||
return this.page.evaluate(_ => new MutationObserver(_ => window.onMutation())
|
||||
.observe(document, { attributes: true, childList: true, subtree: true })
|
||||
);
|
||||
},
|
||||
|
||||
slideCount: function () {
|
||||
return undefined;
|
||||
},
|
||||
|
||||
// A priori knowledge is impossible to achieve in a generic way. Thus the only way is to actually emulate end-user interaction by pressing the configured key and check whether the DOM has changed a posteriori.
|
||||
hasNextSlide: function () {
|
||||
// A priori knowledge is impossible to achieve in a generic way. Thus the only way is to
|
||||
// actually emulate end-user interaction by pressing the configured key and check whether
|
||||
// the DOM has changed a posteriori.
|
||||
hasNextSlide: async function () {
|
||||
if (this.options.maxSlides && this.currentSlide >= this.options.maxSlides)
|
||||
return false;
|
||||
// PhantomJS actually sends a 'keydown' DOM event when sending a 'keypress' user event. Hence 'keypress' event is skipped to avoid moving forward two steps instead of one. See https://github.com/ariya/phantomjs/issues/11094 for more details.
|
||||
['keydown'/*, 'keypress'*/, 'keyup'].forEach(function (event) {
|
||||
this.page.sendEvent(event, this.keycode);
|
||||
}, this);
|
||||
var plugin = this;
|
||||
return new Promise(function (fulfill) {
|
||||
// TODO: use mutation event directly instead of relying on a timeout
|
||||
// TODO: detect cycle to avoid infinite navigation for frameworks that support loopable presentations like impress.js and flowtime.js
|
||||
setTimeout(function () {
|
||||
fulfill(plugin.isNextSlideDetected);
|
||||
}, 1000);
|
||||
});
|
||||
await this.page.press(this.key);
|
||||
// TODO: use mutation event directly instead of relying on a timeout
|
||||
// TODO: detect cycle to avoid infinite navigation for frameworks
|
||||
// that support loopable presentations like impress.js and flowtime.js
|
||||
return new Promise(fulfill => setTimeout(_ => fulfill(this.isNextSlideDetected), 1000));
|
||||
},
|
||||
|
||||
nextSlide: function () {
|
||||
this.isNextSlideDetected = false;
|
||||
},
|
||||
|
||||
currentSlideIndex: function () {
|
||||
var fragment = this.page.evaluate(function () {
|
||||
return window.location.hash.replace(/^#\/?/, '');
|
||||
});
|
||||
currentSlideIndex: async function () {
|
||||
const fragment = await this.page.evaluate(_ => window.location.hash.replace(/^#\/?/, ''));
|
||||
return fragment.length ? fragment : this.currentSlide;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user