Replacing YouTube HTML links with embed code - raku

I'm writing web pages in markdown and converting them to HTML using md2html tool. I want to process the output HTML file and find any youtube link like this:
https://www.youtube.com/watch?v=abcdefgh887
and replace it with the embed code:
<iframe width="560" height="315" src="https://www.youtube.com/embed/abcdefgh887?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
I toyed around a little with Grammars, mostly to get familiar with them, but concluded this probably isn't the ideal tool for the job. Plus I'd prefer to use existing modules that are easily adaptable to other similar tasks rather than roll my own half-baked solution.
Perl5 has some good tools for this kind of thing but I'd like to use a pure Raku solution so I can learn more Raku.
Any recommendations for good approaches to this problem?

OK, found exactly what I needed for this job with DOM::Tiny.
Use it something like this:
my $dom = DOM::Tiny.parse($html);
for $dom.find('a[href]') -> $e {
if $e.text ~~ /^https\:\/\/www\.youtube\.com/ {
my $embed = get_youtube_embed($e.text);
$e.replace($embed)
}
}

I tried to answer your question without knowing an example.
You need to extract youtubeId from A tag and then replace A tag into iframe tag.
pseudo code is:
for each line:
if is youtube A tag,
youtube A tag = youtube Iframe tag
Please paste your input file into my input variable.
const input = `
text1
https://www.youtube.com/watch?v=youtubeId1
text2
text3
https://www.youtube.com/watch?v=youtubeId2
`;
const rx = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?<]*).*/;
const getYoutubeIframe = (youtubeId) => {
return `<iframe width="560" height="315" src="https://www.youtube.com/embed/${youtubeId}?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
}
const output = input.split('\n').map(line => {
const youtubeLink = '<a href="https://www.youtube.com/watch?v=';
if (line.trim().indexOf(youtubeLink) === 0) {
const youtubeId = line.match(rx)[1];
return getYoutubeIframe(youtubeId);
}
return line;
}).join('\n');
console.log(output);

Related

Google script code formatted,colored and beautiful indent

I wrote a container-bound script and now want to make a report from it, by inserting the code into a Google Docs file. The problem is that with copy & paste from the Script Editor, the code is no longer colored or indented. I will need your help because I don't know how to make it well done.
I have this code :
createAndSendDocument() {
// Create a new Google Doc named 'Hello, world!'
var doc = DocumentApp.create('Hello, world!');
// Access the body of the document, then add a paragraph.
doc.getBody().appendParagraph('This document was created by Google Apps Script.');
// Get the URL of the document.
var url = doc.getUrl(); // Get the email address of the active user - that's you.
var email = Session.getActiveUser().getEmail();
}
As tehhowch said you'll need to write your own javascript code to do syntax formatting and then use the output of that.
You can use this https://www.w3schools.com/howto/tryit.asp?filename=tryhow_syntax_highlight they already have the script in place you only need to encode your html and put inside div id="myDiv" and run the javascript code.
<div id="myDiv">
Your encoded html goes here
</div>
Example
<div id="myDiv">
<!DOCTYPE html><br>
<html><br>
<body><br>
<br>
<h1>Testing an HTML Syntax Highlighter</h2><br>
<p>Hello world!</p><br>
<a href="https://www.w3schools.com">Back to School</a><br>
<br>
</body><br>
</html>
</div>
Make sure you first encode your html. [< -> &lt, > -> &gt, etc]
Then you can use the output of that . Sample : https://docs.google.com/document/d/1h8oDOZ0ReTgwxnYt2JKflHWJdlianSWWuBgbWcSdJC0/edit?usp=sharing
Reference and further reads : https://www.w3schools.com/howto/tryit.asp?filename=tryhow_syntax_highlight

Tracking Youtube Embedded videos with SiteCatalyst Omniture

So, I have tried for ages now it seems to track multiple Embedded videos on my test-site with Adobes SiteCatalyst.
Below is the link with documentation I've used
https://gist.github.com/KamalChembath/00106eb266c91777c32e
The problem I've tried to solve is that I want to be able to listen/track already embedded videos, and not actually create the videos using the API and THEN listen to them.
But the documentation "appends" an iframe created by the API into an empty div that needs to have the same id as the iframe id.
But since the embedded video is already there, I don't need this part, obviously.
Please feel free to ask questions if I'm not clear enough.
Anyone had this issue before?
Below is some changes I've made to try to make it append two players into two divs(trying to hack the code I've already got) Putting it all into a for-loop.
Regards everyone!
<div id="player123">
iframe id="player123" type="text/html" width="640" height="390"
src="http://www.youtube.com/embed/-yKNuU8biQo?enablejsapi=1&origin=http://example.com"
frameborder="0"></iframe>
</div>
<div id="player1234">
<iframe id="player1234" type="text/html" width="640" height="390"
src="http://www.youtube.com/embed/VyK-JhjPguY?enablejsapi=1&origin=http://example.com"
frameborder="0"></iframe>
</div>
<script>
var iframeObject = document.getElementsByTagName('iframe');
for ( var i = 0; i < iframeObject.length; i++){
var youtube_id = iframeObject[i].id;
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player(youtube_id, {
videoId: iframeObject[i].src.substring(29, 40),
events: {
'onStateChange': onPlayerStateChange,
'onError' : onPlayerError
}
});
}
</script>

Soundcloud waveform nodes

I was reading a article on soundcloud today about their waveforms and how they generate them by converting the highest volume point into a INT between 0 - 1.
After that I opened the console on chrome and then a track on Soundcloud, going through the networks tab (all files) there was no file returning a array of data to generate the html5 waveform, so my question is how do they do it without requesting the data?
Interesting question :) I'm no expert at HTML5's canvas, but I'm sure it has to do with that.
If you look at the DOM you'll see a structure like this:
<div class="sound__body">
<div class="sound__waveform">
<div class="waveform loaded">
<div class="waveform__layer waveform__scene">
<canvas aria-hidden="true" class="g-box-full sceneLayer" width="453" height="60"></canvas>
<canvas aria-hidden="true" class="g-box-full sceneLayer waveformCommentsNode loaded" width="453" height="60"></canvas>
<canvas aria-hidden="true" class="g-box-full sceneLayer" width="453" height="60"></canvas>
</div>
<div class="commentPlaceholder g-z-index-content">...</div>
<div class="commentPopover darkText smallAvatar small">...</div>
</div>
</div>
</div>
On my page I have four sounds. In my networkpanel I also have four of these:
https://wis.sndcdn.com/iGZOEq0vuemr_m.png
They are being sent as JSON, not as PNG!
And contain stuff like:
{"width":1800,"height":140,"samples":
[111,116,118,124,121,121,116,103,119,120,118,118,119,123,128,128,119,119,119,120,117,116,123,127,124,119,115,120,120,121,120,120,121,121,117,116,117,120,123,119,121,125,128,126,122,99,119,120,121,117,122,120,125,125,134,135,130,126,122,123,120,124,126,124,114,111,119,120,120,118,119,132,133,128,127,
...much more
...much more
122,120,125,125,134,135,130]}
I'm pretty sure this is the data being used to draw the waveform using canvas.
As far as i understand this process.
SoundCloud creates an image directly after the upload.
You can access it via the tracks endpoint.
SC.get('/tracks/159966669', function(sound) {
$('#result').append('<img src="' +sound.waveform_url+'"/>' );
});
I.e. http://jsfiddle.net/iambnz/fzm4mckd/
Then they use a script like that, written by (former) SoundCloud devs, http://waveformjs.org - which converts the image into floats.
Example call:
http://www.waveformjs.org/w?url=https%3A%2F%2Fw1.sndcdn.com%2FzVjqZOwCm71W_m.png&callback=callback_json1
Example response (extract)
callback_json1([0.07142857142857142,0.5428571428571428,0.7857142857142857,0.65,0.6142857142857143,0.6357142857142857,0.5428571428571428,0.6214285714285714,0.6357142857142857,0.6571428571428571,0.6214285714285714,0.5285714285714286,0.6642857142857143,0.5714285714285714,0.5,0.5,0.6,0.4857142857142857,0.4785714285714286,0.5714285714285714,0.6642857142857143,0.6071428571428571,0.6285714285714286,0.5928571428571429,0.6357142857142857,0.6428571428571429,0.5357142857142857,0.65,0.5857142857142857,0.5285714285714286,0.55,0.6071428571428571,0.65,0.6142857142857143,0.5928571428571429,0.6428571428571429,...[....]
See example here, more detailed on waveform.js
HTML
<div class="example-waveform" id="example2">
<canvas width="550" height="50"></canvas>
</div>
JS
SC.get('/tracks/159966669', function(sound) {
var waveform = new Waveform({
container: document.getElementById("example2"),
innerColor: "#666666"
});
waveform.dataFromSoundCloudTrack(sound);
});
http://jsfiddle.net/iambnz/ro1481ga/
See docs here: http://waveformjs.org/#endpoint
I hope this will help you a bit.

Google rending +1 button way above and left of page content

We have implemented google +1 buttons on our site and they have served reliably for some time. However we recently noticed that the buttons are not serving reliably. We rarely see them appear in their designated spaces.
For example on this page: Sample Page : you'll see a gray box of social buttons to left of the page. In it, there is SUPPOSED to be a Google +1 button.
We've requested the button with this code:
<div id="social-google" class="social">
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
<g:plusone size="medium"></g:plusone>
</div>
We've also tried this code:
<div id="social-google" class="social">
<!-- Place this tag where you want the share button to render. -->
<div class="g-plus" data-action="share" data-size="small" data-annotation="bubble"></div>
<!-- Place this tag after the last share tag. -->
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
</div>
Occasionally we'll see a Google +1 button render but, more often than not, the space reserved for the button is apparently blank. When you examine things with firebug, you see that Google HAS attempted to render a button, but for some reason it has placed the button far above and left of the page boundaries.
Here is the top of the html Google generates for the button:
<div id="___plusone_0" style="position: absolute; width: 450px; left: -10000px;">
<iframe id="I0_1377554650466" width="100%" scrolling="no" frameborder="0" hspace="0 marginheight="0" marginwidth="0" style="position:absolute;top:-10000px;width:450px;margin:0px;border-style:none" tabindex="0" vspace="0" name="I0_1377554650466" src="https://apis.google.com/_/+1/fastbutton?bsv=o&usegapi=1&size=medium&hl=en-US&origin=http%3A%2F%2Fwww.comicbookresources.com&url=http%3A%2F%2Fwww.comicbookresources.com%2F%3Fpage%3Darticle%26id%3D47537&gsrc=3p&ic=1&jsh=m%3B%2F_%2Fscs%2Fapps- ...
As you can see Google gave its generated ___plusone_0 div a left position of -10000px and gave the inner iFrame a top position of -10000px. So the button is there. It's just floating out in space. If I manipulate theses position settings (to 0px) the button becomes visible in its appropriate spot.
Any idea why this would happen? Any idea how we can fix this?
You can try adding the following CSS declaration to your stylesheet:
#___plusone_0, #___plusone_0 iframe {
position:static !important;
}
This is a hackaround, so don't depend on it in long term.
Based on an old thread in Drupal Issues.
During the last few days I'm suffering from this problem too. I have a page building app. One of the widgets is google plus: users can enter a url, and the app generates a button. (So there can be more, than 1 button on the page.) Then user saves the page and can see it on Facebook.
Recommendations and observations...
Double check the protocol of google api script. For example, if your website is on https and you are trying to load http://apis.google.com/js/plusone.js, your buttons will probably fail to render.
When I tested this issue on my server, I occasionally opened the app in 2 browser tabs at the same time. Google buttons didn't appear in the first tab, but they did in the second one!
My app requires user to be authorized on Facebook. When I opened the app without authorization, the buttons were shown as expected. But when I logged in and refreshed the page - buttons disappeared.
When I opened the page on Facebook, buttons didn't appear, regardless of whether I was logged in or not.
I beg your pardon, if you think these notices have no sense, but they may save someone's time in future.
Workaround
Suppose, you're parsing the following code:
<!-- google button will be added into this div -->
<div class="googlePlus" data-href="http://google.com"></div>
jQuery function, which parse all .googlePlus divs.
$('.googlePlus').each(function () {
var $googleDiv = $(this);
// check, if button is already parsed
if (!$googleDiv.children().length) {
// add temporary id to the parent div
var $id = 'googlePlus-' + new Date().getTime();
$div.attr({
'id': $id
});
// create, add and render btn (IE compatible method)
var gPlusOne = document.createElement('g:plusone');
gPlusOne.setAttribute('href', $googleDiv.attr('data-href'));
document.getElementById($id).appendChild(gPlusOne);
gapi.plusone.go($id);
// function, correcting css styles
if (!$.isFunction($.fn.fixGooglePlus)) {
$.fn.fixGooglePlus = function () {
$(this).children('div').children('iframe').addBack().css({
position: 'static',
width: 106,
height: 24
});
}
}
// run function, until css is fixed
var $timer = setInterval(function () {
$googleDiv.fixGooglePlus();
if ($googleDiv.find('iframe').css('position') == 'static') {
clearInterval($timer);
$googleDiv.removeAttr('id');
}
}, 100);
} // button hasn't been parsed
});
Put the button code in a a new HTML file and put that file in an iframe. Compared to #U-D13's answer, it's less susceptible to changes by Google.

Prevent divx web plugin fron replacing html5 video element?

For some reason I'm sure the folks at DivX think is important, there is no straightforward way to prevent their plugin from replacing all video elements on your page with they fancy logo.
What I need is a workaround for this, telling the plugin to skip some videos, i.e. not replace them with their playable content.
I got around this by putting an empty HTML 5 video tag, then putting in the video source tags in a JavaScript function in the body onload event. The video then comes up in the normal HTML 5 player and not the DivX web player.
e.g.
This would give the DivX player:
<video width="320" height="240" controls="controls">
<source src="movie.mp4" type="video/mp4" />
</video>
But this would give the normal html 5 player:
<head>
<script type="text/javascript">
function changevid() {
document.getElementById('vid').innerHTML = '<source src="inc/videos/sample1.mp4" type="video/mp4" />';
document.getElementById('vid').load();
}
</script>
</head>
<body onload="changevid()">
<video id="vid" width="800" height="450" controls="controls">
</video>
</body>
At this time, there is no API or means to block the divx plugin from replacing video elements with their placeholder. :-(
i started reverse-engineering the divx-plugin to find out what can be done to hack a way into disabling it. An example, including the complete sourcecode of the divx-plugin, can be found here: http://jsfiddle.net/z4JPB/1/
It currently appears to me that a possible solution could work like this:
create a "clean" backup of the methods appendChild, replaceChild and insertBefore - this has to happen before the content-script from the chrome-extension is executed.
the content-script will execute, overrides the methods mentioned above and adds event-listeners to the DOMNodeInsertedIntoDocument and DOMNodeInserted events
after that, the event-listeners can be removed and the original DOM-Methods restored. You should now be able to replace the embed-elements created by the plugin with the video-elements
It seems, that the plugin is only replacing the video when there are src elements within the video tag. For me it worked by first adding the video tag, and then - in a second thread - add the src tags. However, this doesn´t work in IE but IE had no problem with an insertion of the complete video tag at once.
So following code worked for me in all browsers (of course, jQuery required):
var $container = $('video_container');
var video = 'my-movie';
var videoSrc = '<source src="video/'+video+'.mp4" type="video/mp4"></source>' +
'<source src="video/'+video+'.webm" type="video/webm"></source>' +
'<source src="video/'+video+'.ogv" type="video/ogg"></source>';
if(!$.browser.msie) {
$container.html('<video autoplay loop></video>');
// this timeout avoids divx player to be triggered
setTimeout(function() {
$container.find('video').html(videoSrc);
}, 50);
}
else {
// IE has no problem with divx player, so we add the src in the same thread
$container.html('<video autoplay loop>' + videoSrc + '</video>');
}