smartdown
Version:
A library for translating, rendering and interacting with Smartdown documents. Smartdown is an extension of Markdown that provides richer media support and reactive programming capability.
287 lines (259 loc) • 8.54 kB
JavaScript
/* global smartdown */
/* global window */
/* global smartdownBaseURL */
/* global smartdownDefaultHome */
/* global smartdownGistPathPrefix */
/* global smartdownGistHashPrefix */
/* global smartdownRawPrefix */
/* global smartdownOutputDivSelector */
/* global smartdownMedia */
/* global XMLHttpRequest */
/* eslint no-var: 0 */
var darkMode = false;
function starter() {
var defaultHome = 'Home';
var baseURL = 'https://smartdown.site/';
var rawPrefix = window.location.origin + window.location.pathname;
var gistPathPrefix = '';
var gistHashPrefix = 'gist/';
var outputDivSelector = '#smartdown-output';
var media = {
cloud: '/resources/cloud.jpg',
badge: '/resources/badge.svg',
hypercube: '/resources/Hypercube.svg',
StalactiteStalagmite: '/resources/StalactiteStalagmite.svg',
church: '/resources/church.svg',
lighthouse: '/resources/lighthouse.svg',
barn: '/resources/barn.svg',
'medieval-gate': '/resources/medieval-gate.svg'
};
var multiparts = {};
var inhibitHash = '';
var gistOrg = '';
var gistID = '';
if (typeof smartdownBaseURL === 'string') {
baseURL = smartdownBaseURL;
}
if (typeof smartdownDefaultHome === 'string') {
defaultHome = smartdownDefaultHome;
}
if (typeof smartdownGistPathPrefix === 'string') {
gistPathPrefix = smartdownGistPathPrefix;
}
if (typeof smartdownGistHashPrefix === 'string') {
gistHashPrefix = smartdownGistHashPrefix;
}
if (typeof smartdownRawPrefix === 'string') {
rawPrefix = smartdownRawPrefix;
}
if (typeof smartdownOutputDivSelector === 'string') {
outputDivSelector = smartdownOutputDivSelector;
}
if (typeof smartdownMedia === 'object') {
media = Object.assign(media, smartdownMedia);
}
/* Common code above between inline/blocks helpers */
function cardLoaded(sourceText, cardKey, cardURL) {
if (cardKey === 'README') {
sourceText +=
`
---
[Back to Home](:@${defaultHome})
`;
}
multiparts = smartdown.partitionMultipart(sourceText);
var output = document.querySelectorAll(outputDivSelector)[0];
inhibitHash = '#' + cardKey;
window.location.hash = inhibitHash;
if (darkMode) {
window.location.hash += '?dark=1';
}
// console.log('cardLoaded', cardKey, window.location.hash, window.location.search, window.location);
smartdown.setHome(multiparts._default_, output, function() {
document.body.scrollTop = 0; // For Chrome, Safari and Opera
document.documentElement.scrollTop = 0; // For IE and Firefox
if (!output.id) {
output.id = 'smartdown-output-' + String(Math.random()).slice(2);
}
smartdown.startAutoplay(output);
});
}
function loadAsyncCard(cardKey, cardURL) {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", function() {
cardLoaded(this.responseText, cardKey, cardURL);
});
oReq.open("GET", cardURL);
oReq.send();
}
function relativeCardLoader(cardKey) {
// console.log('relativeCardLoader', cardKey);
cardKey = cardKey.replace(/^#/g, '');
// console.log('# cardKey', cardKey);
// console.log('# gistPathPrefix', gistPathPrefix);
// console.log('# gistHashPrefix', gistHashPrefix);
// console.log('# window.location.pathname', window.location.pathname);
var re = `^/?(${gistPathPrefix})?${gistHashPrefix}([^/]+)/([^/]+)(/(\\w*))?$`;
var gistRE = new RegExp(re, 'g');
var match = gistRE.exec(cardKey);
if (match) {
gistOrg = match[2];
gistID = match[3];
var newCardKey = match[5] || 'Home';
// console.log('cardKey', cardKey, gistOrg, gistID, newCardKey);
cardKey = newCardKey;
}
var part = multiparts[cardKey];
if (part) {
var output = document.querySelectorAll(outputDivSelector)[0];
smartdown.setHome(part, output, function() {
if (!output.id) {
output.id = 'smartdown-output-' + String(Math.random()).slice(2);
}
smartdown.startAutoplay(output);
});
}
else if (cardKey.indexOf('http') === 0 || cardKey.indexOf('/') === 0) {
gistOrg = '';
gistID = '';
loadAsyncCard(cardKey, cardKey);
}
else if (gistOrg !== '' && gistID !== '') {
var gistAPIBase = `https://api.github.com/gists/${gistID}`;
// console.log('gistAPIBase', gistAPIBase);
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", function() {
var gistResponse = JSON.parse(this.responseText);
// console.log('gist Response', gistResponse);
var gistFile = gistResponse.files[cardKey + '.md'];
// console.log('gistFile', gistFile);
var gistFileURL = gistFile.raw_url;
cardKey = `${gistHashPrefix}${gistOrg}/${gistID}/${cardKey}`;
loadAsyncCard(cardKey, gistFileURL);
});
oReq.open("GET", gistAPIBase);
oReq.send();
}
else {
gistOrg = '';
gistID = '';
var suffix = (cardKey === '') ? '' : (cardKey + '.md');
var cardURL = rawPrefix + suffix;
loadAsyncCard(cardKey, cardURL);
}
}
function loadHome() {
var hash = window.location.hash;
var args = '';
var argsPos = hash.indexOf('?');
if (argsPos >= 0) {
args = hash.slice(argsPos);
hash = hash.slice(0, argsPos);
// console.log('loadHome hashargs', hash, args, window.location.search);
darkMode = (args === '?dark=1');
var container = document.getElementById('smartdown-outer-container');
if (container) {
if (darkMode) {
container.classList.add('smartdown-dark');
}
else {
container.classList.remove('smartdown-dark');
}
}
}
if (hash === '') {
hash = defaultHome;
}
relativeCardLoader(hash);
}
var calcHandlers = smartdown.defaultCalcHandlers;
var replace = rawPrefix;
function gistPrefix(href) {
var result = href;
var hash = window.location.hash;
var args = '';
var argsPos = hash.indexOf('?');
if (argsPos >= 0) {
args = hash.slice(argsPos);
hash = hash.slice(0, argsPos);
console.log('gistPrefix hashargs', hash, args, window.location.search);
}
if (gistPathPrefix.length > 0 && window.location.pathname.endsWith(gistPathPrefix)) {
var re = `^/?(${gistPathPrefix})?${gistHashPrefix}([^/]+)/([^/]+)(/(\\w*))?$`;
var gistRE = new RegExp(re, 'g');
var match = gistRE.exec(hash);
if (match) {
let gistOrg = match[2].replace('#', '');
let gistID = match[3];
result = `https://gist.githubusercontent.com/${gistOrg}/${gistID}/raw/`;
}
}
else if (gistHashPrefix.length > 0 && hash.indexOf('#' + gistHashPrefix) === 0) {
var re = `^#${gistHashPrefix}([^/]+)/([^/]+)(/(\\w*))?$`;
var gistRE = new RegExp(re, 'g');
var match = gistRE.exec(hash);
if (match) {
let gistOrg = match[1];
let gistID = match[2];
result = `https://gist.githubusercontent.com/${gistOrg}/${gistID}/raw/`;
}
}
return result;
}
const linkRules = [
{
prefix: '/block/',
replace: gistPrefix
},
{
prefix: 'block/',
replace: gistPrefix
},
{
prefix: 'assets/',
replace: replace + 'assets/'
},
{
prefix: '/assets/',
replace: replace + 'assets/'
},
{
prefix: 'content/',
replace: replace + 'content/'
},
{
prefix: '/content/',
replace: replace + 'content/'
},
{
prefix: '/resources/',
replace: baseURL === '' ? '/resources/' : baseURL + 'lib/resources/'
},
];
function locationHashChanged() {
var hash = window.location.hash;
var args = '';
var argsPos = hash.indexOf('?');
if (argsPos >= 0) {
args = hash.slice(argsPos);
hash = hash.slice(0, argsPos);
darkMode = (args === '?dark=1');
var container = document.getElementById('smartdown-outer-container');
if (container) {
if (darkMode) {
container.classList.add('smartdown-dark');
}
else {
container.classList.remove('smartdown-dark');
}
}
}
if (inhibitHash !== hash) {
relativeCardLoader(hash.slice(1));
}
return false;
}
window.onhashchange = locationHashChanged;
smartdown.initialize(media, baseURL, loadHome, relativeCardLoader, calcHandlers, linkRules);
};
window.smartdownStarter = starter;