How to use Markdown with MathJax like Math StackExchange - javascript

UPDATED POST
Ok I've managed to make Markdown and MathJax work together, it was relatively simple actually. I've used marked together with MathJax.
$(function() {
var $text = $("#text"), // the markdown textarea
$preview = $("#preview"); // the preview div
$text.on("keyup", function() {
$preview.html( marked($text.val()) ); // parse markdown
MathJax.Hub.Queue(["Typeset", MathJax.Hub, "preview"]); // then let MathJax do its job
})
});
Problem now is: I think markdown is parsing my math 1st before MathJax can change it. How do i fix this? I think its fixed on Math StackOverflow, but how? I need to stop markdown from parsing math
UPDATE 2
This works, but not sure if its the way math.stackexchange does it, but it seems to produce similar/same results with what I tested so far ...
$(function() {
var $text = $("#text"),
$preview = $("#preview");
$text.on("keyup", function() {
$preview.html( $text.val() );
MathJax.Hub.Queue(["Typeset", MathJax.Hub, "preview"]);
});
MathJax.Hub.Register.MessageHook("End Process", function (message) {
$preview.html( marked($preview.html()) );
});
});
OLD POST BELOW
In the math stackexchange, I can use MathJax with Markdown. I wonder what do I need to do that? I can use a library like marked to render Markdown, but for MathJax, it seems like it just renders on page loads. How can I call it to re-render or better just render whats needed (specified by me)
html = marked("some markdown string") // a HTML string
// is there something like
html = MathJax.parse(html)
UPDATE
I think I should be looking at http://www.mathjax.org/docs/1.1/typeset.html#manipulating-individual-math-elements. But when I try
$text.on("keyup", function() {
$preview.html( marked($text.val()) );
var math = MathJax.Hub.getAllJax("preview");
console.log(math);
MathJax.Hub.Queue(["Text", math, "a+b"]);
})
Where:
$text: is the jQuery element for my textarea
$preview: is the preview div
I find that math is undefined, so it seems var math = MathJax.Hub.getAllJax("preview") is not working. I have a div#preview btw.

The fastest way is to protect the math from your markdown-parser.
See this question for a detailed answer by Davide Cervone, including a link to the code used by math.SE.

For sublime, add the following code to Markdown Preview --> Settings - User,
{
/*
Enable or not mathjax support.
*/
"enable_mathjax": true
}
as shown below,
Refer to How to enable MathJax rendering in Sublimetext Markdown Preview.

Related

Change thousands sign using JS

Here I would like to replace in the draggable slider the "," sign used for the thousands into this sign " ' " (a quote mark).
I am currently using a plugin to render the table (from a JSON file) so I cannot alter the HTML.
I am able to change the sign, in fact on page load the sign seems correct, but as soon I drag the slider the separator changes to a comma again.
I saw that the data is rendered from the Plugin with a comma in the aria-valuetext="" attribute: <div class="noUi-handle noUi-handle-upper" data-handle="1" tabindex="0" role="slider" aria-orientation="horizontal" aria-valuemin="0.0" aria-valuemax="100.0" aria-valuenow="100.0" aria-valuetext="2,290.00"><div class="noUi-tooltip">2,290.00</div></div>
I tried using this code without any results:
<script>
window.onload = function(){
var div = document.querySelectorAll('.noUi-tooltip');
div.forEach(function(r) {
var text = r.textContent;
var output = text.replace(/[,|]/g, "'");
r.innerHTML = output;
});
}
</script>
What am I writing wrong?
I am using WordPress and the wpdatatables plugin.
I'm not sure about the plugin you've used for your slider but perhaps you can try this for now:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type == "attributes") {
var parentEl = document.getElementsByClassName('noUi-handle-upper');
var childEl = parentEl.childNodes[0];
childEl.innerHTML = childEl.innerHTML.replace(',', '\'');
}
});
});
observer.observe(document.getElementsByClassName('noUi-handle-upper')[0], {
attributes: true,
});
It's using MutationObserver which is not supported by older browsers. You can read more about it at https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver.
This is because you modify the string just in the beginning (on load).
This is why the code works in the beginning but doesn't work later, because it runs once and then stops.
I don't know how to use WordPress or sliders, but I'd advise you to use an 'on value changed' command, so the text will change to whatever you want it to each time the slider's value is changed.
I will post this now but I'll review your code and will try to update this with more exact information later.

Casper/Phantomjs unable to retrieve highest resolution src image

I am trying to make a basic Instagram web scraper, both art inspiration pictures and just generally trying to boost my knowledge and experience programming.
Currently the issue that I am having is that Casper/Phantomjs can't detect higher res images from the srcset, and I can't figure out a way around this. Instagram has their srcsets provide 640x640, 750x750, and 1080x1080 images. I would obviously like to retrieve the 1080, but it seems to be undetectable by any method I've tried so far. Setting the viewport larger does nothing, and I can't retrieve the entire source set through just getting the HTML and splitting it where I need it. And as far as I can tell, there is no other way to retrieve said image than to get it from this srcset.
Edit
As I was asked for more details, here I go. This is the code I used to get the attributes from the page:
function getImages() {
var scripts = document.querySelectorAll('._2di5p');
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute('src');
});
}
Then I do the standard:
casper.waitForSelector('div._4rbun', function() {
this.echo('...found selector ...try getting image srcs now...');
imagesArray = this.evaluate(getImages);
imagesArray.forEach(function (item) {
console.log(item);
However, all that is returned is the lowest resolution of the srcset. Using this url, for example, (https://www.instagram.com/p/BhWS4csAIPS/?taken-by=kasabianofficial) all that is returned is https://instagram.flcy1-1.fna.fbcdn.net/vp/b282bb23f82318697f0b9b85279ab32e/5B5CE6F2/t51.2885-15/s640x640/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg, which is the lowest resolution (640x640) image in the srcset. Ideally, I'd like to retrieve the https://instagram.flcy1-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg which is the 1080x1080 image in the srcset. But I can't. There's no way to get that item as far as I can tell. It's completely hidden.
I found a way around it in Instagram's case. Instagram puts the source picture in a meta tag within the head. So, using the code I'll paste below, you can call all of the meta tags and then sort out which one is the source picture by checking if "og:image" is retrieved.
function getImages() {
var scripts = document.querySelectorAll('meta[content]');
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute('property') + " " + e.getAttribute('content');
});
}
And this is the way to sort the meta tags into only having the original image in its native resolution.
this.echo('...found selector ...try getting image srcs now...');
imagesArray = this.evaluate(getImages);
imagesArray.forEach(function (item) {
if (typeof item == "string" && item.indexOf('og:image') > -1) {
Edit: Unfortunately this only works for single image posts on Instagram (the site I'm trying to scrape) so this unfortunately does me no goo. The values within the meta tags don't change even if you load the next image in the post. I'm leaving this up though in case anyone else could use it, but it's not ideal for my own use case.
Yes indeed PhantomJS doesn't seem to support srcset, its Webkit engine is very old.
But to be fair, all the metadata related to the page is out in the open in the HTML as JSON in window._sharedData variable.
If you want to use a headless browser (and not parse it with any server-side language) you can do this:
var imgUrl = page.evaluate(function(){
return window._sharedData.entry_data.PostPage[0].graphql.shortcode_media.display_resources[2].src;
});
https://instagram.fhen2-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg
Solution: So my solution was to use slimerjs. If I run the js file through "casperjs --engine=slimerjs fileName.js", I can retrieve srcsets in full. So if I say use this code:
function getImgSrc() {
var scripts = document.querySelectorAll("._2di5p");
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute("srcset");
});
}
on this url (https://www.instagram.com/p/BhWS4csAIPS/?taken-by=kasabianofficial) I will get (https://instagram.flcy1-1.fna.fbcdn.net/vp/b282bb23f82318697f0b9b85279ab32e/5B5CE6F2/t51.2885-15/s640x640/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg 640w,https://instagram.flcy1-1.fna.fbcdn.net/vp/b4eebf94247af02c63d20320f6535ab4/5B6258DF/t51.2885-15/s750x750/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg 750w,https://instagram.flcy1-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg 1080w) as the result.
This is what I wanted as it means I can scrape those 1080 images. Sorry for this messy page, but I wanted to leave my trail of steps to any of those who might be trying like me.

Render Markdown in text that's coming from a live preview in Javascript

I'm working on a website with ruby on rails where people can make posts and what not. The posts use Markdown for rendering the text just like Stack Overflow. Whenever a user is making a post, there is a live preview div right beneath the text area that show's the user what their post will look like, just like here on stack overflow. My problem is I don't know how to get the Markdown to render on the live preview.
My javascript code for the live preview is
window.onload = function(){
var idea = document.getElementById("idea-text");
try{
idea.onkeyup = idea.onkeypress = function(){
document.getElementById('live-preview').innerHTML = this.value.replace(/\n/g, '<br/>');
}
}
catch(e){
}
}
The text will always be plain text, any pointers on making the Markdown render?
Edit:
My solution to my dilemma was to use markdown-js from https://github.com/evilstreak/markdown-js Figuring out how to use this with node was painful however because I ran into multiple problems. I found a solution on https://rails-assets.org/#/components/markdown which provided a simple three step solution to my problem! My code to show a live-preview of text that renders mark down is
window.onload = function(){
var idea = document.getElementById("idea-text");
try{
idea.onkeyup = idea.onkeypress = function(){
document.getElementById('live-preview').innerHTML = markdown.toHTML(this.value);
}
}
catch(e){
}
}
You can use a library like markdown-js that expose a simple method to convert a markdown conte in html, then directly inject your html in your preview div.
Pretty sure StackOverflow uses PageDown to do the translation from markdown to HTML in JavaScript.
PageDown is the JavaScript Markdown previewer used on Stack Overflow and the rest of the Stack Exchange network. It includes a Markdown-to-HTML converter and an in-page Markdown editor with live preview.
You could conceivably do something like this in the end:
var converter = new pagedown.Converter();
idea.onkeyup = idea.onkeypress = function(){
document.getElementById('live-preview').innerHTML = converter.makeHtml(this.value);
}

How to trigger a JavaScript function using the URL

I really didn't know how to explain my question in the title, so I tried.
Anyways, this is my problem. I have a webpage which is basically a puzzle. The basic premise of it is that when you visit a certain link, it will trigger a function and show the next piece.
Here's one of the functions that will show the piece -
function showone() {
var elem = document.getElementById("one");
if (elem.className = "hide") {
elem.className = "show"
}
}
The reason that it's built like this, is because the pieces are constructed and placed using an HTML table, using classes to hide and show them.
What I need to do, is somehow create a URL that will trigger a new piece. For example, "www.website.com/index.html?showone" is what I'd like. This would trigger the "showone" function.
I don't know how to do this though, and after a fair bit of searching, I'm more confused than I was to begin with.
The reason I'm using JavaScript to begin with, is that the page can't refresh. I understand that this might not be possible, in which case, I'm open to any suggestions on how I could get this to work.
Thanks in advance, any suggestions would be greatly appreciated.
-Mitchyl
Javascript web application frameworks can to this for you, they allow to build web application without refresh page.
For example you can use backbonejs it has Router class inside and it very easy to use.
code is easy as :
var Workspace = Backbone.Router.extend({
routes: {
"help": "help", // #help
"search/:query": "search", // #search/kiwis
"search/:query/p:page": "search" // #search/kiwis/p7
},
help: function() {
...
},
search: function(query, page) {
...
}
});
is also you can use angularjs it is big one that supports by Google.
Maybe this solution can help you?
$("a.icon-loading-link").click(function(e){
var link = $(e.target).prop("href"); //save link of current <a> into variable
/* Creating new icon-tag, for example $("<img/>", {src: "link/to/file"}).appendTo("next/dt"); */
e.preventDefault(); //Cancel opening link
return false; //For WebKit browsers
});

text going blank once [ ] gets replaced by < >

I have the following code
$(document).ready(function () {
$(".page").on('click', function () {
$("#ctl00_MainContent_dfComments").html(function (i, val) {
return val.replace(/\]/g, '>');
});
});
$(".page").on('click', function () {
$("#ctl00_MainContent_dfComments").text(function (i, val) {
return val.replace(/\[/g, "<");
});
});
});
Which with the help of replacing characters in entire document JQuery works wonderfully. However, when the < bracket is inserted, the entire div goes blank. I can replace the [ with anything, but as soon as I put in < everything inside that div disappears. Any idea of what might be going on?
Yes, this is supposed to create a bold (kind of like a bb parser)
Your second replace is using .text() instead of .html(). As a side note, you can also combine the two event handlers.
$(document).ready(function () {
$(".page").on('click', function () {
$("#ctl00_MainContent_dfComments").html(function (i, val) {
return val.replace(/\]/g, '>').replace(/\[/g, '<');
});
});
});​
Here it is in action: http://jsfiddle.net/pbnDP/8/
Pressing the button makes the text go bold.
The obvious security concerns are discussed in the comments on the main post. Don't put this on a site where users can generate the content this is being run on.
It looks like your probably not ending up with Valid HTML and the DOM rendering the html is disposing of any invalid HTML for you.
Theres a few problems with your script - the first it that it promotes dangerous html, your appear not to be doing any form of sanity or blacklist/whitelist checking on the code.
The other issue is your manually naming ASP.NET IDs - this is bad since they can change. Use .ClientID instead.
$(".page").on('click', function () {
$("#ctl00_MainContent_dfComments").html(function (i, val) {
return val.replace(/\[/g, "<");
});
});
.html might work better then text, and also use class name or clientid to select elements with like John suggested in his answer , that is not good to guess what the browser is going to change the id to.
Pleas check your DOM again, seems like browser either detects the < > as html tag or html aint valid.
Working version: http://jsfiddle.net/pbnDP/
I do know in few programming world including Ruby there is somthing called html_safe you might want to use alongside this.
Hope it helps.

Categories