Skip to content

Instantly share code, notes, and snippets.

@edjafarov
Created December 6, 2016 18:42
Show Gist options
  • Save edjafarov/97ab021cbd9e52aa89db9a4e4e0c7a08 to your computer and use it in GitHub Desktop.
Save edjafarov/97ab021cbd9e52aa89db9a4e4e0c7a08 to your computer and use it in GitHub Desktop.
var mdIt = require('markdown-it'),
MarkdownItVideo =require('markdown-it-video')
md = new mdIt();
md.use(MarkdownItVideo);
md.use(videoPlugin);
console.log(md.render('$[video](https://videos.contentful.com/9sf2shpojqu3/4lW8CjEX2UsYuMeKY2eo4k/8445be5ffdc2eb10650bdd9560a24215/675_DieterBlum_Trailer_en.mp4 https://images.contentful.com/9sf2shpojqu3/1lmIs3xvpKYikwAOAe0kiK/3ebec843171ad8f4c1735526c2bb7816/677-337224-12__2_.jpg)'))
//The implementation is taken from
//https://github.com/brianjgeiger/markdown-it-video/blob/master/index.js
// Process $[video](contentful-video-url)
/*
API:
$[video](https://videos.contentful.com/vpx322qexe3h/1kvcghNoxauKoYSk6gWIAI/16868f3923186fa49325a2343e498240/431_435_Supersale_final.mp4)
$[video](https://videos.contentful.com/ loop autoplay)
$[video](https://videos.contentful.com/ loop)
*/
'use strict';
const videoTypes = {
'mp4': 'video/mp4',
'webm': 'video/webm',
'ogv': 'video/ogg'
};
var players = {};
var videoRegex = /^https:\/\/videos.contentful.com\/(.+)$/;
var imageRegex = /^(https:\/\/[^\s]*\.jpe?g|png|gif|bmp)$/i;
var EMBED_REGEX = /\$\[([a-zA-Z].+)\]\([\s]*([^)]*?)[\s]*[\)]/im;
var defaults = {
url: videoUrl,
video: {},
};
function videoPlugin(md, options = {}) {
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var opts = _extends({}, options, defaults);
md.renderer.rules.video = tokenizeVideo(md, opts);
console.log('i1', md.renderer.rules.video);
md.inline.ruler.before('emphasis', 'video', videoEmbed(md, opts));
console.log('i2');
};
function init(el) {
const videPlaceholder = el.querySelector('[data-video-src]');
const src = videPlaceholder && videPlaceholder.getAttribute('data-video-src');
const id = videPlaceholder && videPlaceholder.getAttribute('id');
const options = videPlaceholder && videPlaceholder.getAttribute('options');
if (!videPlaceholder || !src) return;
if (!window.flowplayer) {
const script = document.createElement('script');
script.setAttribute('async', true);
script.onload = playVideo.bind(this, videPlaceholder, src, id, options);
script.src = '/_assets/flow-player/flowplayer.min.js';
document.body.appendChild(script);
const style = document.createElement('link');
style.setAttribute('async', true);
style.rel = 'stylesheet';
style.href = '/_assets/flow-player/skin/minimalist.css';
document.querySelector('head').appendChild(style);
}
else {
playVideo(videPlaceholder, src, id, options);
}
};
function destroy(el) {
const videPlaceholder = el.querySelector('[data-video-src]');
const id = videPlaceholder && videPlaceholder.getAttribute('id');
if (players[id]) {
players[id].unload();
delete players[id];
}
};
function playVideo(videPlaceholder, src, id, options) {
const videoExtension = src.split('.').pop().toLowerCase();
var config = {
embed: false,
swf: '/_assets/flow-player/flowplayer.swf',
muted: true,
ratio: 9 / 16,
key: window.conf.flowPlayerLicense || '$127465123735801',
onBeforeUnload: ()=>true,
clip: {
sources: [{
type: videoTypes[videoExtension],
src: src
}]
}
},
listOfOptionsToApply = options.split(','),
videoPreviewNode = document.getElementById(`${id}-preview`);
if (videoPreviewNode) {
videoPreviewNode.onclick = function() {
players[id].play();
videoPreviewNode.className += ' playing';
};
}
config = listOfOptionsToApply.reduce((conf, option) => {
conf[option] = true;
return conf;
}, config);
players[id] = window.flowplayer(videPlaceholder, config);
players[id].one('ready', () => {
if (config.autoplay) players[id].play();
});
}
function videoParser(url) {
var match = url.match(videoRegex);
return match ? match[1] : url;
}
function videoEmbed(md, options) {
function videoReturn(state, silent) {
var serviceEnd,
serviceStart,
token,
oldPos = state.pos,
match,
service,
videoID,
optsID,
firstImage,
serviceLower,
newState;
if (state.src.charAt(oldPos) !== '$'/* @ */ ||
state.src.charCodeAt(oldPos + 1) !== 0x5B/* [ */) {
return false;
}
match = /\$\[([a-zA-Z].+)\]\([\s]*([^)]*?)[\s]*[\)]/im.exec(state.src);
console.log(match)
if (!match || match.length < 3) {
return false;
}
service = match[1];
videoID = match[2];
optsID = videoID.split(' ');
if (Array.isArray(optsID)) {
videoID = optsID.shift();
firstImage = optsID.reduce((result, opt) => {
if (result) return result;
if (imageRegex.test(opt)) return opt;
return null;
}, null);
}
else {
optsID = null;
}
console.log(1)
serviceLower = service.toLowerCase();
if (serviceLower === 'video') {
videoID = videoParser(videoID);
}
else if (!options[serviceLower]) {
return false;
}
console.log(2)
// If the videoID field is empty, regex currently make it the close parenthesis.
if (videoID === ')') {
videoID = '';
}
console.log(3)
serviceStart = oldPos + 2;
serviceEnd = md.helpers.parseLinkLabel(state, oldPos + 1, false);
//
// We found the end of the link, and know for a fact it's a valid link;
// so all that's left to do is to call tokenizer.
//
console.log(4)
if (!silent) {
state.pos = serviceStart;
state.posMax = serviceEnd;
state.service = state.src.slice(serviceStart, serviceEnd);
newState = new state.md.inline.State(service, state.md, state.env, []);
newState.md.inline.tokenize(newState);
token = state.push('video', '');
token.videoID = videoID;
token.optsID = optsID;
token.firstImage = firstImage;
token.service = service;
token.level = state.level;
}
console.log(5)
state.pos = state.pos + state.src.indexOf(')', state.pos);
state.posMax = state.tokens.length;
return true;
}
return videoReturn;
}
function videoUrl(service, videoID) {
switch (service) {
case 'video':
return '//videos.contentful.com/' + videoID;
}
}
function tokenizeVideo(md, options) {
function tokenizeReturn(tokens, idx) {
console.log('i6');
const videoID = md.utils.escapeHtml(tokens[idx].videoID);
const service = md.utils.escapeHtml(tokens[idx].service).toLowerCase();
const videoOpts = tokens[idx].optsID && tokens[idx].optsID.join(',');
const uniqueId = Math.floor(Math.random()*999999);
console.log('i5');
const firstImageBlock = tokens[idx].firstImage ? `<div class="md-video__preview" id="${uniqueId}-preview"><img src="${tokens[idx].firstImage}" class="md-video__preview-image"/>
<div class="md-video__preview-play-button">
<div class="md-video__preview-circle">
</div>
<div class="md-video__preview-inner-circle">
</div>
</div>
</div>` : '';
return videoID === '' ? '' :
`<div class="flow-player-wrapper">
<div id="${uniqueId}" data-video-src="${videoUrl(service, videoID, options)}" options="${videoOpts || ''}"></div>
${firstImageBlock}
</div>`;
}
return tokenizeReturn;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment