Created
December 6, 2016 18:42
-
-
Save edjafarov/97ab021cbd9e52aa89db9a4e4e0c7a08 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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