This commit is contained in:
Estevao Soares dos Santos 2017-12-14 12:48:41 +00:00
parent 7fbf406dda
commit 9a9b41f906
13 changed files with 373 additions and 80 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/node_modules

View File

@ -0,0 +1,65 @@
«««
title: Annoucement: Showdown 2.0,
author: Estevão Soares dos Santos,
author_avatar: img/avatars/tivie.jpg,
date: 2017-12-12,
language: en,
image: img/blog/2017.12.12.jpg,
summary: Showdown version 1.0.0 was released almost 3 years ago, back in May 2015.
Since then, it has seen a lot of improvements, with a boost to performance and a significant number of features now
included in the core of the library. However, do to backwards compatibility constrains, we are still supporting a
lot of legacy features, that prevent us from moving the software forward.
With that in mind, **it is time to start thinking about Showdown version 2.0.**
For the next major release of Showdown we have planned a range of **significant changes and additions**.
»»»
Showdown version 1.0.0 was released almost 3 years ago, back in May 2015.
Since then, it has seen a lot of improvements, with a boost to performance and
a significant number of features now included in the core of the library.
However, do to backwards compatibility constrains, we are still supporting a lot
of legacy features, that prevent us from moving the software forward.
With that in mind, **it is time to start thinking about Showdown version 2.0.**
For the next major release of Showdown we have planned a range of **significant changes
and additions**. Here are a few of the most important ones:
## Reverse Conversion (HTML to MD)
Being a popular request by our users, we though that a new major version is the perfect
opportunity to implement this feature.
This feature requires a number of changes throughout the code and API. For instance,
the extension system must be redesigned to allow for extensions to hook unto both
processes (HTML->MD and MD->HTML). Event and option names must also reflect this
since, as they stand now, they might cause confusion.
## Extensions
We are (finally) **completely dropping support for legacy extensions**. Although there are a
couple old ones still in the wild, most of them (if not all) have already
migrated to the modern extension system.
We are also revamping the extension system. For starters, **we're dropping old "lang"
and "output" extension in favour of event extensions**.
The **API of event extensions will also change** in order to mimic the browser events
and play nicely with other libraries and frameworks.
## Subparsers
**Subparsers will also see a major code refactoring**, with performance improvements.
Although performance is no longer an issue, mainly due to the way new browsers
handle Regular Expressions, there are a couple of issues that still need to be addressed.
Most of the issues can be fixed if we drop support for old browsers and old nodejs versions.
## Development
Formally, Showdown 2.0 will start development in the beginning of 2018 and all
development efforts will be put into it.
This means **Showdown 1.x will now enter maintenance mode, that is, no new features
will be added** and only important bugfixes will be committed.
We expect to release a stable version of Showdown 2.0 somewhere around June 2018,
but an alpha-version might be released a lot sooner. ***So, if you are as excited as
we are, stay tuned for more information***.

BIN
blog/img/2017.12.12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

16
blog/posts.json Normal file
View File

@ -0,0 +1,16 @@
[
{
"id": 1,
"canonical": "annoucement-showdown-2.0",
"url": "blog/annoucement-showdown-2.0.md",
"metadata": {
"title": "Annoucement: Showdown 2.0",
"author": "Estevão Soares dos Santos",
"author_avatar": "img/avatars/tivie.jpg",
"date": "2017-12-12",
"language": "en",
"image": "blog/img/2017.12.12.jpg",
"summary": "Showdown version 1.0.0 was released almost 3 years ago, back in May 2015. Since then, it has seen a lot of improvements, with a boost to performance and a significant number of features now included in the core of the library. However, do to backwards compatibility constrains, we are still supporting a lot of legacy features, that prevent us from moving the software forward.\n\nWith that in mind, **it is time to start thinking about Showdown version 2.0.** For the next major release of Showdown we have planned a range of **significant changes and additions**."
}
}
]

View File

@ -1,4 +1,8 @@
/** typography **/
body {
font-family: 'Open Sans', sans-serif;
}
h1, h2, h3, h4, h5, h6 {
}
@ -7,7 +11,14 @@ h1, h2, h3, h4, h5, h6 {
font-family: 'Anonymous Pro', monospace;
}
/** loading spinner **/
.loadingoverlay {
background: url('../img/background-color.svg') no-repeat fixed center;
background-size: cover !important;
}
.loadingoverlay_fontawesome {
color: #584b4f;
}
/** COLORS **/
@ -199,6 +210,8 @@ a:active {
#mainNavigation a.active {
color: #a29f99;
pointer-events: none;
cursor: default;
}
#mainNavigation .navbar-toggler {
@ -305,6 +318,34 @@ h3[id$="breaking-changes"] {
}
/** BLOG **/
.blog-article .authoring-info {
margin-bottom: 1em;
padding-bottom: 1.5em;
height: 30px;
line-height: 30px;
border-top: 1px solid #8abaad;
}
.blog-article .authoring-info img {
height: 22px;
width: auto;
}
.blog-article {
padding-top: 1em;
padding-bottom: 3em;
}
.blog-article h2 {
margin-bottom: 0.5em;
}
.blog-article section.content p {
line-height: 2em;
}
/** highlightjs override **/
.hljs {
padding-top: 1em;

37
html/blog-article.html Normal file
View File

@ -0,0 +1,37 @@
<section id="blog-post" class="page-section text-bg-light">
<div class="container">
<div id="blog-post-container"></div>
</div>
</section>
<template id="blog-article-tpl" style="display: none;">
<article class="blog-article">
<header><h2>{{metadata.title}}</h2></header>
<section class="authoring-info">
<p>
<time datetime="{{metadata.date}}">
<i class="fa fa-calendar" aria-hidden="true"></i> {{metadata.date}}
</time>&nbsp;&nbsp;&nbsp;
<span class="author"><img src="{{metadata.author_avatar}}"> {{metadata.author}}</span>
</p>
</section>
{{#metadata.image}}
<figure><img src="{{metadata.image}}" class="img-fluid"></figure>
{{/metadata.image}}
<section class="content">
{{{post}}}
</section>
</article>
</template>
<script>
(function () {
console.log('foo');
var canonical = $('#param-canonical').attr('value');
console.log($('#param-canonical'));
$.when(blogPosts.getPostByCanonical(canonical)).then(function(post) {
var article = Mustache.render($('#blog-article-tpl').html(), post);
$('#blog-post-container').html(article);
router.updatePageLinks();
});
})();
</script>

View File

@ -1,6 +1,36 @@
<section id="documentation" class="page-section text-bg-light">
<div class="container">
<h1>Blog</h1>
<p class="lead">Coming soon!!</p>
<div id="articles-wrapper">
</div>
</div>
</section>
</section>
<template id="blog-list-article-tpl">
<article class="blog-article">
<header><h2>{{metadata.title}}</h2></header>
<section class="authoring-info">
<p>
<time datetime="{{metadata.date}}">
<i class="fa fa-calendar" aria-hidden="true"></i> {{metadata.date}}
</time>&nbsp;&nbsp;&nbsp;
<span class="author"><img src="{{metadata.author_avatar}}"> {{metadata.author}}</span>
</p>
</section>
{{#metadata.image}}
<figure><img src="{{metadata.image}}" class="img-fluid"></figure>
{{/metadata.image}}
<section class="content">{{{metadata.summary}}}</section>
<div class="blog-read-more"><a href="#!/blog/{{canonical}}" data-navigo>Read more&nbsp;<i class="fa fa-chevron-right" aria-hidden="true"></i></a></div>
</article>
</template>
<script>
$.when(blogPosts.getList()).then(function(list) {
var articleWrapper = $('#articles-wrapper');
for (var i = 0; i < list.length; ++i) {
var article = Mustache.render($('#blog-list-article-tpl').html(), list[i]);
articleWrapper.append(article);
}
router.updatePageLinks();
});
</script>

View File

@ -79,10 +79,10 @@ var html = converter.makeHtml(md);</code></pre>
<section id="sponsors" class="page-section text-bg-light">
<div class="container">
<h1>Sponsors</h1>
<h1>Friends of <span class="showdown-brand">Show<span class="text-secondary">down</span></span></h1>
<div class="row">
<div class="col-md-3"><img alt="jetbrains" class="img-fluid" src="img/jetbrains.svg"></div>
<div class="col-md-3"><img alt="zapier" class="img-fluid" src="img/zapier-logo.png"></div>
<div class="col-md-3"><a href="https://www.jetbrains.com/"><img alt="jetbrains" class="img-fluid" src="img/jetbrains.svg"></a></div>
<div class="col-md-3"><a href="https://zapier.com/"><img alt="zapier" class="img-fluid" src="img/zapier-logo.png"></a></div>
</div>
</div>
</section>

View File

@ -1,12 +1,6 @@
<section id="releases" class="page-section text-bg-light">
<div class="container">
<h1>Releases</h1>
<div id="release-spinner">
<center>
<i class="fa fa-spinner fa-spin fa-3x fa-fw text-primary"></i><br>
<span>Loading...</span>
</center>
</div>
<div class="row">
<aside id="releases-list" class="col-2">
<ul class="nav flex-column"></ul>
@ -71,8 +65,5 @@
hljs.highlightBlock(block);
hljs.lineNumbersBlock(block);
});
// remove loading symbol
$('#release-spinner').html('');
});
</script>

BIN
img/avatars/tivie.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -21,7 +21,7 @@
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="theme-color" content="#ffffff">
<link href="https://fonts.googleapis.com/css?family=Anonymous+Pro" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Anonymous+Pro|Open+Sans" rel="stylesheet">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css"
integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb"
@ -47,11 +47,11 @@
</button>
<div class="collapse navbar-collapse justify-content-end" id="mainNavigationLinks">
<div class="navbar-nav">
<a href="#!/home" data-href="html/main.html" class="nav-item nav-link internal-navigation active">Home</a>
<a href="#!/releases" data-href="html/releases.html" class="nav-item nav-link internal-navigation">Releases</a>
<a href="http://demo.showdownjs.com" data-href="html/releases.html" class="nav-item nav-link" target="_blank">Demo</a>
<a href="#!/documentation" data-href="html/documentation.html" class="nav-item nav-link internal-navigation">Documentation</a>
<a href="#!/blog" data-href="html/blog.html" class="nav-item nav-link internal-navigation">Blog</a>
<a data-navigo id="navlink-home" href="#!/home" class="nav-item nav-link internal-navigation active">Home</a>
<a data-navigo id="navlink-releases" href="#!/releases" class="nav-item nav-link internal-navigation">Releases</a>
<a data-navigo id="navlink-documentation" href="#!/documentation" class="nav-item nav-link internal-navigation">Documentation</a>
<a data-navigo id="navlink-blog" href="#!/blog" class="nav-item nav-link internal-navigation">Blog</a>
<a href="http://demo.showdownjs.com" class="nav-item nav-link" target="_blank">Demo</a>
</div>
</div>
</div>
@ -60,7 +60,7 @@
<header id="call-to-action" class="jumbotron jumbotron-fluid">
<div class="container">
<div class="positioner">
<h2 class="display-2 showdown-brand"><span>Show</span><span class="text-secondary">down</span></h2>
<h1 class="display-2 showdown-brand"><span>Show</span><span class="text-secondary">down</span></h1>
<p class="lead">A Markdown to HTML converter written in Javascript!</p>
<div>
<a id="lt-version-lnk" class="btn btn-primary btn-lg download-button" href="https://github.com/showdownjs/showdown/releases/latest" role="button">Download <em id="lt-version-num"></em></a><br>
@ -75,7 +75,7 @@
</div>
</header>
<article id="page"></article>
<main id="page"></main>
<section id="donate" class="page-section blackboard">
@ -107,12 +107,19 @@
</div>
</footer>
<datalist id="page-params" style="display: none"></datalist>
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.8.5/showdown.min.js" integrity="sha256-rnlCzq7mhN7HlGWkWJ539aucrpHWZOFa/9SqlQvKxjQ=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js" integrity="sha256-iaqfO5ue0VbSGcEiQn+OeXxnxAMK2+QgHXIDA5bWtGI=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@1.5.4/src/loadingoverlay.min.js"></script>
<!--<script src="https://cdn.jsdelivr.net/npm/gasparesganga-jquery-loading-overlay@1.5.4/extras/loadingoverlay_progress/loadingoverlay_progress.min.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.1.0/highlightjs-line-numbers.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
<script src="https://unpkg.com/navigo@6"></script>
<script src="js/app.js"></script>
<script>
hljs.initHighlightingOnLoad();

200
js/app.js
View File

@ -1,71 +1,173 @@
latestVersion = 0;
var converter = new showdown.Converter({
metadata: true,
tables: true,
strikethrough: true,
ellipsis: true,
headerLevelStart: 3
});
/** ROUTING **/
var router = new Navigo('http://showdownjs.com/', true, '#!');
/** BLOG POSTS **/
var blogPosts = {};
$(document).ready(function() {
blogPosts = new BlogPosts();
getLatestVersion();
function BlogPosts () {
var posts = [];
var indexedList = {};
function loadPage(url) {
$('#page')
.load(url, function () {
console.log('navigate to ' + url);
$('#page').find('pre>code').each(function(i, block) {
hljs.highlightBlock(block);
hljs.lineNumbersBlock(block);
var getList = this.getList = function() {
var dfd = jQuery.Deferred();
if (posts.length !== 0) {
dfd.resolve(posts);
} else {
$.getJSON('blog/posts.json', function(data) {
for (var i = 0; i < data.length; ++i) {
data[i].metadata.summary = converter.makeHtml(data[i].metadata.summary);
}
dfd.resolve(data);
});
})
}
return dfd.promise();
};
this.getPostByCanonical = function(canonical) {
var dfd = jQuery.Deferred();
var idx = null;
if (typeof indexedList[canonical] !== 'undefined') {
idx = indexedList[canonical];
}
$.when(getList()).then(function(list) {
if (idx !== null) {
dfd.resolve(list[idx]);
} else {
for (var i = 0; i < list.length; ++i) {
if (list[i].canonical === canonical) {
var promise = $.ajax({
url: list[i].url,
dataType: "text"
});
promise.done((function (index, listItem) {
return function (md) {
listItem.post = converter.makeHtml(md);
posts[index] = listItem;
indexedList[canonical] = index;
dfd.resolve(listItem);
};
})(i, list[i]));
return;
}
}
dfd.resolve(null);
}
});
return dfd.promise();
};
}
function getCurrentUrl (router) {
var uriSplit = window.location.href.split('#!');
var defaultShebang = '#!/home';
var shebang = '';
var currentUrl = '';
if (typeof uriSplit[1] === 'undefined') {
shebang = defaultShebang;
} else {
shebang = '#!' + uriSplit[1];
}
if (router.hasOwnProperty(shebang)) {
currentUrl = router[shebang];
} else {
currentUrl = router[defaultShebang];
}
return currentUrl;
}
$(document).ajaxStart(function(){
$.LoadingOverlay('show', {
image: '',
//color: 'rgba(166, 200, 157, 0.7)',
color: '#fff',
fontawesome: 'fa fa-spinner fa-spin'
});
});
$(document).ajaxStop(function(){
$.LoadingOverlay("hide");
});
function getLatestVersion() {
$.getJSON('https://api.github.com/repos/showdownjs/showdown/releases/latest', function (data) {
$('#lt-version-num').html('v' + data.tag_name);
$('#lt-version-lnk').attr('href', data.zipball_url);
latestVersion = data.tag_name;
var dfd = jQuery.Deferred();
if (typeof Cookies.get('version') === 'undefined' || typeof Cookies.get('zipball') === 'undefined') {
$.getJSON('https://api.github.com/repos/showdownjs/showdown/releases/latest', function (data) {
var version = data.tag_name;
var zipball = data.zipball_url;
Cookies.set('version', version, { expires: 0.1 });
Cookies.set('zipball', zipball, { expires: 0.1 });
dfd.resolve({version: version, zipball: zipball});
});
} else {
dfd.resolve({
version: Cookies.get('version'),
zipball: Cookies.get('zipball')
});
}
return dfd.promise();
}
function loadPage(url) {
var $page = $('#page');
return $page.load(url, function () {
$page.find('pre>code').each(function(i, block) {
hljs.highlightBlock(block);
hljs.lineNumbersBlock(block);
router.updatePageLinks();
});
});
}
function injectParams(params) {
if (typeof params !== 'undefined') {
// pass params to page
for (var param in params) {
if (params.hasOwnProperty(param)) {
var $pageParams = $('#page-params');
$pageParams.html();
$pageParams.append('<data id="param-' + param + '" value="'+ params[param] +'" hidden style="display: none;"></data>');
console.log(params[param]);
}
}
}
}
$('.internal-navigation').click(function(evt) {
function changeActiveLink(name) {
$('.internal-navigation').removeClass('active');
$(this).addClass('active');
$('#navlink-' + name).addClass('active');
}
var url = $(this).attr('data-href');
//load page
loadPage(url);
$.when(getLatestVersion()).then(
function(data) {
$('#lt-version-num').html('v' + data.version);
$('#lt-version-lnk').attr('href', data.zipball);
}
);
router
.on('/releases', function () {
changeActiveLink('releases');
return loadPage('html/releases.html');
})
.on('/documentation', function () {
changeActiveLink('documentation');
return loadPage('html/documentation.html');
})
.on('/blog/:canonical', function (params) {
changeActiveLink('blog');
injectParams(params);
return loadPage('html/blog-article.html', params);
})
.on('/blog', function () {
changeActiveLink('blog');
return loadPage('html/blog.html');
})
.on('*', function () {
changeActiveLink('home');
return loadPage('html/main.html');
})
.resolve();
$('.internal-navigation').click(function() {
// smooth scroll to page
$('html, body').animate({
scrollTop: $('#page').offset().top
}, 500);
});
})
var router = {};
$('.internal-navigation').each(function () {
var shebang = $(this).attr('href');
router[shebang] = $(this).attr('data-href');
});
// load page on startup
loadPage(getCurrentUrl(router));
});

View File

@ -4,11 +4,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<url>
<loc>http://showdownjs.com/</loc>
<lastmod>2017-12-11T20:11:04+00:00</lastmod>
<url>
<loc>http://showdownjs.com/</loc>
<lastmod>2017-12-14T20:11:04+00:00</lastmod>
</url>
<url>
<loc>http://showdownjs.com/#!/documentation</loc>
@ -16,10 +15,14 @@
</url>
<url>
<loc>http://showdownjs.com/#!/releases</loc>
<lastmod>2017-12-11T20:11:04+00:00</lastmod>
<lastmod>2017-12-14T20:11:04+00:00</lastmod>
</url>
<url>
<loc>http://showdownjs.com/#!/blog</loc>
<lastmod>2017-12-11T20:11:04+00:00</lastmod>
<lastmod>2017-12-14T20:11:04+00:00</lastmod>
</url>
<url>
<loc>http://showdownjs.com/#!/blog/annoucement-showdown-2.0</loc>
<lastmod>2017-12-14T12:46:23+00:00</lastmod>
</url>
</urlset>