How to create a showdown.js markdown extension - javascript

Using the following code, I get working output:
<html>
<head>
<script type="text/javascript" src="/js/showdown.js"></script>
</head>
<body>
<script type="text/javascript">
var converter = new Showdown.converter();
alert(converter.makeHtml('*test* abc'));
</script>
</body>
</html>
Returning <p><em>test</em> abc</p>
I would now like to add an extension. The github page suggests this can be done with:
<script src="src/extensions/twitter.js" />
var converter = new Showdown.converter({ extensions: 'twitter' });
However, modifying my code to:
<html>
<head>
<script type="text/javascript" src="/js/showdown.js"></script>
<script type="text/javascript" src="/js/twitter.js"></script>
</head>
<body>
<script type="text/javascript">
var converter = new Showdown.converter({ extensions: 'twitter' });
alert(converter.makeHtml('*test* abc'));
</script>
</body>
</html>
Produces the error
"Uncaught Extension 'undefined' could not be loaded. It was either not found or is not a valid extension."
Adding the following code (as listed under the Filter example)
var demo = function(converter) {
return [
// Replace escaped # symbols
{ type: 'lang', function(text) {
return text.replace(/\\#/g, '#');
}}
];
}
Produces an error Uncaught SyntaxError: Unexpected token (
I would like to create an extension like this one https://github.com/rennat/python-markdown-oembed to interpret a ![video](youtube_link), but it's unclear how to begin adding this support.

In your last block you have a comma after 'lang', followed immediately with a function. This is not valid json.
EDIT
It appears that the readme was incorrect. I had to to pass an array with the string 'twitter'.
var converter = new Showdown.converter({extensions: ['twitter']});
converter.makeHtml('whatever #meandave2020');
// output "<p>whatever #meandave2020</p>"
I submitted a pull request to update this.

The way we write extensions has changed, I found some help with the following filter example : http://codepen.io/tivie/pen/eNqOzP
showdown.extension("example", function() {
'use strict';
return [
{
type: 'lang',
filter: function(text, converter, options) {
var mainRegex = new RegExp("(^[ \t]*:>[ \t]?.+\n(.+\n)*\n*)+", "gm");
text = text.replace(mainRegex, function(match, content) {
content = content.replace(/^([ \t]*):>([ \t])?/gm, "");
var foo = converter.makeHtml(content);
return '\n<blockquote class="foo">' + foo + '</blockquote>\n';
});
return text;
}
}
]
});

Related

Highlight code with Markdown-it.js and Highlight.js

In the current example, a Markdown snippet is ported to HTML and the output is shown in the DIV (ID Content).
The highlight function (hljs.highlight) is set to the options markdown-it (md). However, this is not carried out.
What do I have to change so that the output uses the highlight.js?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release#10.2.1/build/styles/default.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/11.0.1/markdown-it.min.js "></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.1/highlight.min.js"></script>
</head>
<body>
<div id="content"></div>
<script>
var md = window.markdownit();
md.set({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs"><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>';
} catch (__) {}
}
return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
}
});
var result = md.render('# markdown-it rulezz! \n\n```html <pre><code class="js">function test();</code></pre>```');
document.getElementById('content').innerHTML = result;
</script>
</body>
</html>
Hope it's not too late.
You must break line (\n) after your fenced code block.
So this:
var result = md.render('# markdown-it rulezz! \n\n```html <pre><code class="js">function test();</code></pre>```');
Should be:
var result = md.render('# markdown-it rulezz! \n\n ```html \n <pre><code class="js">function test();</code></pre>\n```');
This is how everything should be:
the .js files should be:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/11.0.1/markdown-it.min.js "></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.1/highlight.min.js"></script>
These are okay.
As for the .css, you can use the one you are using or you can use the one that is in the npm:
npm install markdown-it-highlight
get the .css file at node_modules/markdown-it-highlight/dist/index.css, that has nicer syntax highlighting color and use that.
Then you would have to set this defaults object and set this on the defaults.highlight:
var defaults = {
html: false, // Enable HTML tags in source
xhtmlOut: false, // Use '/' to close single tags (<br />)
breaks: false, // Convert '\n' in paragraphs into <br>
langPrefix: 'language-', // CSS language prefix for fenced blocks
linkify: true, // autoconvert URL-like texts to links
typographer: true, // Enable smartypants and other sweet transforms
// options below are for demo only
_highlight: true, // <= THIS IS WHAT YOU NEED
_strict: false,
_view: 'html' // html / src / debug
};
// and then do this:
defaults.highlight = function (str, lang) {
var esc = md.utils.escapeHtml;
console.log(str)
console.log(lang)
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs"><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>';
} catch (__) {}
}else{
return '<pre class="hljs"><code>' + esc(str) + '</code></pre>';
}
};
// now set the md:
md = window.markdownit(defaults);
// now this is where you forgot the line break after the fenced code block:
const result = md.render('# markdown-it rulezz! \n ```html \n <pre><code class="js">function test();</code></pre>\n```');
document.querySelector('#content').innerHTML = result;
I outlined a few of the steps needed to get code highlighting working here: https://github.com/microsoft/AdaptiveCards/discussions/8081#discussioncomment-4219420
Summary:
Easy Way
First, make sure you support Markdown in cards:
import MarkdownIt from 'markdown-it'
// For Markdown in Adaptive Cards.
window.markdownit = MarkdownIt
Now we'll use another library to color code:
import highlight from 'highlight.js'
import 'highlight.js/styles/github.css'
Run:
highlight.highlightAll()
to update all your cards.
If you run it twice, then it will try to update cards that it already updated, and you'll get warnings. See https://github.com/microsoft/AdaptiveCards/discussions/8081#discussioncomment-4219420 for handling dynamically added cards.

Javascript Not Running in HTML

Given the following:
HTML
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<table>
<tr class='foo'><td>one</td></tr>
<tr class='foo'><td>two</td></tr>
<tr class='foo'><td>three</td></tr>
</table>
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script type="text/javscript" src="https://gist.githubusercontent.com/anonymous/d25940992da18e05f3f2d50889f6a4c2/raw/f013565c33d17abb33a4f5ad7717aae090873516/test.js"></script>
</body>
</html>
JS
// Generated by CoffeeScript 1.10.0
(function() {
var hasChildren, rowsWithChildren;
$(function() {
return console.log('starting');
});
$(function() {
var filtered, rows;
console.log('here');
rows = $('tr');
filtered = rowsWithChildren(rows);
return console.log(filtered);
});
rowsWithChildren = function(rows) {
return _.filter(rows, function(r) {
return hasChildren(r);
});
};
hasChildren = function(row) {
return row.children().length === 1;
};
}).call(this);
When I open that HTML page in my Chrome Browser, I see the table on the screen. But, I don't see any console.log ... statements in the output of the Developer Tools Console.
Also, when I look at Dev Tool's Sources, I don't see the JS from gist.github.com....
What's wrong with this HTML?
There's two problems with what you're attempting to do:
There's a typo on the line where you link to the Gist - should be text/javascript not text/javscript.
Github doesn't allow you to hotlink to code/assets hosted on their website - essentially you can't use them as a CDN. Here's a blog post from them explaining this in more detail.
The third script element has a wrong type value. With a wrong value, the loaded file will not be interpreted as JavaScript.
So change:
<script type="text/javscript" ...
to:
<script type="text/javascript" ...
As I remember there is "onready" problem in this version of jQuery (I may be mistaken).
As for "text/javascript" it's unnecessary nowadays.
Try to merge your two $(function(){}) into one, and remove these "returns" inside them. Like this:
(function() {
var hasChildren, rowsWithChildren;
$(function() {
console.log('starting');
var filtered, rows;
console.log('here');
rows = $('tr');
filtered = rowsWithChildren(rows);
console.log(filtered);
});
rowsWithChildren = function(rows) {
return _.filter(rows, function(r) {
return hasChildren(r);
});
};
hasChildren = function(row) {
return row.children().length === 1;
};
}).call(this);
Hope it helps.

Backbone: getting the html code of a view?

In order to write the HTML code of social icons (Twitter, Linkedin, etc) to a textarea so that the user can use that code elsewhere, I would like to get the HTML code of the view element, but I'm having some issues. To help illustrate this better, here is the code that creates the view:
define(function(require, exports, module) {
var _ = require('underscore');
var GridControlView = require('pb/views/grid-control');
var SocialiconsControlDialog = require('pb/views/socialicons-control-dialog');
var template = require('text!pb/templates/socialicons-grid-control.html');
var SocialiconsGridControlView = GridControlView.extend({
template: _.template(template)
,templateVars: {
partials: {
facebook: require('text!pb/templates/socialicons-grid-control-facebook.html')
,twitter: require('text!pb/templates/socialicons-grid-control-twitter.html')
,googleplus: require('text!pb/templates/socialicons-grid-control-googleplus.html')
,pinterest: require('text!pb/templates/socialicons-grid-control-pinterest.html')
,linkedin: require('text!pb/templates/socialicons-grid-control-linkedin.html')
}
}
,control_dialog: SocialiconsControlDialog
});
return SocialiconsGridControlView;
});
And, for example, the Linkedin template looks like this:
<script src="//platform.linkedin.com/in.js?<%- t.cache_buster %>" type="text/javascript">lang: en_US</script>
<script type="IN/Share" data-counter="<%- t.linkedin_option_countmode %>"></script>
What I would like to retrieve, is the parsed template code as text, something such as:
<script type="text/javascript" src="//platform.linkedin.com/in.js?0.4670609195438331">
<script data-counter="top" type="IN/Share+init">
But using something such as:
control_view.render().$el.innerHTML;, control_view.render().$el.html().text() or control_view.render().$el.html().replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, ""); doesn't return text; it returns the full HTML, and produces a Linkedin icon (when I just want the text to be written to a textarea).
Any thoughts?
Update **
I noticed that the code control_view.render().$el is working correctly on other places of the application, and returning HTML code, but for some reason in this view where I'm trying it doesn't. The code seems to break at:
$control = control_view.render().el;
and in the console I get an error which is:
TypeError: t is undefined - underscore-min.js (line 3)
Use the .outerHTML property of the $el.
var html = $('<script type="text/javascript" src="//platform.linkedin.com/in.js?0.4670609195438331">' +
'<script data-counter="top" type="IN/Share+init">');
var text = html[0].outerHTML;
$('textarea').val(text);
jsFiddle

Concatenate Strings in JavaScript

I Have edited the code, the updated code is below, This code is not able to fetch the keywords meta tag, hence it is not working.
old description: I am trying to concatinate the strings to get the finalUrl, but I am not able to do so becuase of the tags variable. I need to fetch the keywords meta tag of the page and append it to get the finalUrl. Any help?
<script type="text/javascript">
var tags=$('meta[name=keywords]').attr("content");
var gameurl = "http://xyz/abc/details/";
var jsn = ".json?callback=showGameDetail";
var finalUrl= gameurl.concat(tags).concat(jsn);
function loadJSON(url) {
var headID = document.getElementsByTagName("head")[0];
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = url;
headID.appendChild(newScript);
}
function showGameDetail(feed){
var title = feed.title;
var game_url = feed.pscomurl;
var packart_url = feed.Packart;
$("#bnr-ads-box").html("<img src='"+"http://abc.com/"+packart_url+"'>");
}
loadJSON(finalUrl);
</script>
<div id="bnr-ads-box"></div>
<!DOCTYPE html>
<html>
<head>
<meta id="metaK" name="keywords" content="customizable software for QuickBooks, QuickBooks-integrated, Method customization, CRM accounting, Method for QuickBooks, Method CRM, Method blog, Salesforce automation, Method online platform, QuickBooks customization, web-based platform, industry-specific, customer portal, Method Field Services, Method Manufacturing, ERP" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<p id="demo">Click the button to join two strings into one new string.</p>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction()
{
var tags=$('meta[name=keywords]').attr("content");
var gameurl = "http://xyz/abc/names/";
var jsn = ".json?callback=showGameDetail";
var finalUrl= gameurl.concat(tags).concat(jsn);
document.getElementById("demo").innerHTML=finalUrl;
}
</script>
</body>
</html>
change this
var tags="$('meta[name=keywords]').attr("content");";
to
var tags=$('meta[name=keywords]').attr("content");
also use this code var finalUrl = gameurl + tags + jsn;
What you need is to escape the double quotes inside your tags variable, like so:
var tags="$('meta[name=keywords]').attr(\"content\");";
Cris' solution is also fine, but in some case you will need to have two sets of double quotes inside a string so you will be forced to do escaping correctly.
FYI: Escaping is the process of having special characters getting generated in a string which would otherwise cause issues, for instance in javascript you can't have newlines in a string, like this:
var mystring = 'on
a different line'; // <- this causes a syntax error
So one would do the following:
var mystring = 'on\na different line';
You forgot to include the jquery
<!DOCTYPE html>
<html>
<head>
<meta name="keywords" content="hello"/>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
function myFunction()
{
alert("Hello World!");
var tags=$('meta[name=keywords]').attr("content");
var gameurl = "http://xyz/abc/names/";
var jsn = ".json?callback=showGameDetail";
var finalUrl= gameurl.concat(tags).concat(jsn);
alert(finalUrl);
}
</script>
</head>
<body>
<button onclick="myFunction()">Try it</button>
</body>
</html>
Tough debatable, you can use an array, which can be concatenated by calling join():
var tags = $('meta[name=keywords]').attr("content");
var data = [
"http://xyz/abc/names/",
encodeURIComponent(tags),
".json?callback=showGameDetail"
].join('');
$("#demo").html(data);
Actually the concat method works on strings too (in chrome at least) but the recommended method is using the plus concatenation string operator
You are however missing some stuff
jQuery library - I assume you want that since you have $(...) in the example
encoding of the string from the keywords - I use encodeURIComponent to handle possible newlines and quotes in the keywords
.
<!DOCTYPE html>
<html>
<head>
<title>Create a URL from keywords</title>
<meta name="keywords" content="These are tags" />
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
function myFunction() {
var tags = $('meta[name=keywords]').attr("content");
var URL ="http://xyz/abc/names/" +
encodeURIComponent(tags) +
".json?callback=showGameDetail";
window.console && console.log(URL);
$("#demo").html(URL);
}
</script>
<body>
<p id="demo">Click the button to join two strings into one new string.</p>
<button onclick="myFunction()">Try it</button>
</body>
</html>

Why doesn't JSON.parse work?

Why doesn't JSON.parse behave as expected?
In this example, the alert doesn't fire:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testing JSON.parse</title>
<script type="text/javascript" src="js/json2.js">
// json2.js can be found here: https://github.com/douglascrockford/JSON-js/blob/master/json2.js
</script>
<script type="text/javascript">
function testJSONParse()
{
var text = '[{"a":"w","b","x"},{"a":"y","b":"z"}]';
alert(JSON.parse(text));
}
window.onload = testJSONParse;
</script>
</head>
<body>
</body>
</html>
In firefox, the Error Console says "JSON.parse". Not very descriptive..
This is a simplification of a problem I have which uses AJAX to fetch data from a database and acquires the result as a JSON string (a string representing a JSON object) of the same form as text in the example above.
Your JSON is not formatted correctly:
var text = '[{"a":"w","b","x"},{"a":"y","b":"z"}]';
^-- This should be a ':'
It should be:
var text = '[{"a":"w","b":"x"},{"a":"y","b":"z"}]';
error in typing
var text = '[{"a":"w","b":"x"},{"a":"y","b":"z"}]';
//below is correct one
var text = '[{"a":"w","b":"x"},{"a":"y","b":"z"}]';
alert(JSON.parse(text));

Categories

Resources