|
@@ -1,534 +0,0 @@
|
|
|
-/* globals marked, unfetch, ES6Promise, Promise */ // eslint-disable-line no-redeclare
|
|
|
-
|
|
|
-if (!window.Promise) {
|
|
|
- window.Promise = ES6Promise;
|
|
|
-}
|
|
|
-if (!window.fetch) {
|
|
|
- window.fetch = unfetch;
|
|
|
-}
|
|
|
-
|
|
|
-onunhandledrejection = function(e) {
|
|
|
- throw e.reason;
|
|
|
-};
|
|
|
-
|
|
|
-var $loadingElem = document.querySelector('#loading');
|
|
|
-var $mainElem = document.querySelector('#main');
|
|
|
-var $markdownElem = document.querySelector('#markdown');
|
|
|
-var $markedVerElem = document.querySelector('#markedVersion');
|
|
|
-var $commitVerElem = document.querySelector('#commitVersion');
|
|
|
-var $markedVer = document.querySelector('#markedCdn');
|
|
|
-var $optionsElem = document.querySelector('#options');
|
|
|
-var $outputTypeElem = document.querySelector('#outputType');
|
|
|
-var $inputTypeElem = document.querySelector('#inputType');
|
|
|
-var $responseTimeElem = document.querySelector('#responseTime');
|
|
|
-var $previewElem = document.querySelector('#preview');
|
|
|
-var $previewIframe = document.querySelector('#preview iframe');
|
|
|
-var $permalinkElem = document.querySelector('#permalink');
|
|
|
-var $clearElem = document.querySelector('#clear');
|
|
|
-var $htmlElem = document.querySelector('#html');
|
|
|
-var $lexerElem = document.querySelector('#lexer');
|
|
|
-var $panes = document.querySelectorAll('.pane');
|
|
|
-var $inputPanes = document.querySelectorAll('.inputPane');
|
|
|
-var lastInput = '';
|
|
|
-var inputDirty = true;
|
|
|
-var $activeOutputElem = null;
|
|
|
-var search = searchToObject();
|
|
|
-var markedVersions = {
|
|
|
- master: 'https://cdn.jsdelivr.net/gh/markedjs/marked/lib/marked.js'
|
|
|
-};
|
|
|
-var markedVersionCache = {};
|
|
|
-var delayTime = 1;
|
|
|
-var checkChangeTimeout = null;
|
|
|
-var markedWorker;
|
|
|
-
|
|
|
-$previewIframe.addEventListener('load', handleIframeLoad);
|
|
|
-
|
|
|
-$outputTypeElem.addEventListener('change', handleOutputChange, false);
|
|
|
-
|
|
|
-$inputTypeElem.addEventListener('change', handleInputChange, false);
|
|
|
-
|
|
|
-$markedVerElem.addEventListener('change', handleVersionChange, false);
|
|
|
-
|
|
|
-$markdownElem.addEventListener('change', handleInput, false);
|
|
|
-$markdownElem.addEventListener('keyup', handleInput, false);
|
|
|
-$markdownElem.addEventListener('keypress', handleInput, false);
|
|
|
-$markdownElem.addEventListener('keydown', handleInput, false);
|
|
|
-
|
|
|
-$optionsElem.addEventListener('change', handleInput, false);
|
|
|
-$optionsElem.addEventListener('keyup', handleInput, false);
|
|
|
-$optionsElem.addEventListener('keypress', handleInput, false);
|
|
|
-$optionsElem.addEventListener('keydown', handleInput, false);
|
|
|
-
|
|
|
-$commitVerElem.style.display = 'none';
|
|
|
-$commitVerElem.addEventListener('keypress', handleAddVersion, false);
|
|
|
-
|
|
|
-$clearElem.addEventListener('click', handleClearClick, false);
|
|
|
-
|
|
|
-Promise.all([
|
|
|
- setInitialQuickref(),
|
|
|
- setInitialOutputType(),
|
|
|
- setInitialText(),
|
|
|
- setInitialVersion()
|
|
|
- .then(setInitialOptions)
|
|
|
-]).then(function() {
|
|
|
- handleInputChange();
|
|
|
- handleOutputChange();
|
|
|
- checkForChanges();
|
|
|
- setScrollPercent(0);
|
|
|
- $loadingElem.style.display = 'none';
|
|
|
- $mainElem.style.display = 'block';
|
|
|
-});
|
|
|
-
|
|
|
-function setInitialText() {
|
|
|
- if ('text' in search) {
|
|
|
- $markdownElem.value = search.text;
|
|
|
- } else {
|
|
|
- return fetch('./initial.md')
|
|
|
- .then(function(res) { return res.text(); })
|
|
|
- .then(function(text) {
|
|
|
- if ($markdownElem.value === '') {
|
|
|
- $markdownElem.value = text;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function setInitialQuickref() {
|
|
|
- return fetch('./quickref.md')
|
|
|
- .then(function(res) { return res.text(); })
|
|
|
- .then(function(text) {
|
|
|
- document.querySelector('#quickref').value = text;
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function setInitialVersion() {
|
|
|
- return fetch('https://data.jsdelivr.com/v1/package/npm/marked')
|
|
|
- .then(function(res) {
|
|
|
- return res.json();
|
|
|
- })
|
|
|
- .then(function(json) {
|
|
|
- for (var i = 0; i < json.versions.length; i++) {
|
|
|
- var ver = json.versions[i];
|
|
|
- markedVersions[ver] = 'https://cdn.jsdelivr.net/npm/marked@' + ver + '/lib/marked.js';
|
|
|
- var opt = document.createElement('option');
|
|
|
- opt.textContent = ver;
|
|
|
- opt.value = ver;
|
|
|
- $markedVerElem.appendChild(opt);
|
|
|
- }
|
|
|
- })
|
|
|
- .then(function() {
|
|
|
- return fetch('https://api.github.com/repos/markedjs/marked/commits')
|
|
|
- .then(function(res) {
|
|
|
- return res.json();
|
|
|
- })
|
|
|
- .then(function(json) {
|
|
|
- markedVersions.master = 'https://cdn.jsdelivr.net/gh/markedjs/marked@' + json[0].sha + '/lib/marked.js';
|
|
|
- })
|
|
|
- .catch(function() {
|
|
|
- // do nothing
|
|
|
- // uses url without commit
|
|
|
- });
|
|
|
- })
|
|
|
- .then(function() {
|
|
|
- if (search.version) {
|
|
|
- if (markedVersions[search.version]) {
|
|
|
- return search.version;
|
|
|
- } else {
|
|
|
- var match = search.version.match(/^(\w+):(.+)$/);
|
|
|
- if (match) {
|
|
|
- switch (match[1]) {
|
|
|
- case 'commit':
|
|
|
- addCommitVersion(search.version, match[2].substring(0, 7), match[2]);
|
|
|
- return search.version;
|
|
|
- case 'pr':
|
|
|
- return getPrCommit(match[2])
|
|
|
- .then(function(commit) {
|
|
|
- if (!commit) {
|
|
|
- return 'master';
|
|
|
- }
|
|
|
- addCommitVersion(search.version, 'PR #' + match[2], commit);
|
|
|
- return search.version;
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 'master';
|
|
|
- })
|
|
|
- .then(function(version) {
|
|
|
- $markedVerElem.value = version;
|
|
|
- })
|
|
|
- .then(updateVersion);
|
|
|
-}
|
|
|
-
|
|
|
-function setInitialOptions() {
|
|
|
- if ('options' in search) {
|
|
|
- $optionsElem.value = search.options;
|
|
|
- } else {
|
|
|
- setDefaultOptions();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function setInitialOutputType() {
|
|
|
- if (search.outputType) {
|
|
|
- $outputTypeElem.value = search.outputType;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function handleIframeLoad() {
|
|
|
- lastInput = '';
|
|
|
- inputDirty = true;
|
|
|
-}
|
|
|
-
|
|
|
-function handleInput() {
|
|
|
- inputDirty = true;
|
|
|
-}
|
|
|
-
|
|
|
-function handleVersionChange() {
|
|
|
- if ($markedVerElem.value === 'commit' || $markedVerElem.value === 'pr') {
|
|
|
- $commitVerElem.style.display = '';
|
|
|
- } else {
|
|
|
- $commitVerElem.style.display = 'none';
|
|
|
- updateVersion();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function handleClearClick() {
|
|
|
- $markdownElem.value = '';
|
|
|
- $markedVerElem.value = 'master';
|
|
|
- $commitVerElem.style.display = 'none';
|
|
|
- updateVersion().then(setDefaultOptions);
|
|
|
-}
|
|
|
-
|
|
|
-function handleAddVersion(e) {
|
|
|
- if (e.which === 13) {
|
|
|
- switch ($markedVerElem.value) {
|
|
|
- case 'commit':
|
|
|
- var commit = $commitVerElem.value.toLowerCase();
|
|
|
- if (!commit.match(/^[0-9a-f]{40}$/)) {
|
|
|
- alert('That is not a valid commit');
|
|
|
- return;
|
|
|
- }
|
|
|
- addCommitVersion('commit:' + commit, commit.substring(0, 7), commit);
|
|
|
- $markedVerElem.value = 'commit:' + commit;
|
|
|
- $commitVerElem.style.display = 'none';
|
|
|
- $commitVerElem.value = '';
|
|
|
- updateVersion();
|
|
|
- break;
|
|
|
- case 'pr':
|
|
|
- $commitVerElem.disabled = true;
|
|
|
- var pr = $commitVerElem.value.replace(/\D/g, '');
|
|
|
- getPrCommit(pr)
|
|
|
- .then(function(commit) {
|
|
|
- $commitVerElem.disabled = false;
|
|
|
- if (!commit) {
|
|
|
- alert('That is not a valid PR');
|
|
|
- return;
|
|
|
- }
|
|
|
- addCommitVersion('pr:' + pr, 'PR #' + pr, commit);
|
|
|
- $markedVerElem.value = 'pr:' + pr;
|
|
|
- $commitVerElem.style.display = 'none';
|
|
|
- $commitVerElem.value = '';
|
|
|
- updateVersion();
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function handleInputChange() {
|
|
|
- handleChange($inputPanes, $inputTypeElem.value);
|
|
|
-}
|
|
|
-
|
|
|
-function handleOutputChange() {
|
|
|
- $activeOutputElem = handleChange($panes, $outputTypeElem.value);
|
|
|
- updateLink();
|
|
|
-}
|
|
|
-
|
|
|
-function handleChange(panes, visiblePane) {
|
|
|
- var active = null;
|
|
|
- for (var i = 0; i < panes.length; i++) {
|
|
|
- if (panes[i].id === visiblePane) {
|
|
|
- panes[i].style.display = '';
|
|
|
- active = panes[i];
|
|
|
- } else {
|
|
|
- panes[i].style.display = 'none';
|
|
|
- }
|
|
|
- }
|
|
|
- return active;
|
|
|
-}
|
|
|
-
|
|
|
-function addCommitVersion(value, text, commit) {
|
|
|
- if (markedVersions[value]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- markedVersions[value] = 'https://cdn.jsdelivr.net/gh/markedjs/marked@' + commit + '/lib/marked.js';
|
|
|
- var opt = document.createElement('option');
|
|
|
- opt.textContent = text;
|
|
|
- opt.value = value;
|
|
|
- $markedVerElem.insertBefore(opt, $markedVerElem.firstChild);
|
|
|
-}
|
|
|
-
|
|
|
-function getPrCommit(pr) {
|
|
|
- return fetch('https://api.github.com/repos/markedjs/marked/pulls/' + pr + '/commits')
|
|
|
- .then(function(res) {
|
|
|
- return res.json();
|
|
|
- })
|
|
|
- .then(function(json) {
|
|
|
- return json[json.length - 1].sha;
|
|
|
- }).catch(function() {
|
|
|
- // return undefined
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function setDefaultOptions() {
|
|
|
- if (window.Worker) {
|
|
|
- messageWorker({
|
|
|
- task: 'defaults',
|
|
|
- version: markedVersions[$markedVerElem.value]
|
|
|
- });
|
|
|
- } else {
|
|
|
- var defaults = marked.getDefaults();
|
|
|
- setOptions(defaults);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function setOptions(opts) {
|
|
|
- $optionsElem.value = JSON.stringify(
|
|
|
- opts,
|
|
|
- function(key, value) {
|
|
|
- if (value && typeof value === 'object' && Object.getPrototypeOf(value) !== Object.prototype) {
|
|
|
- return undefined;
|
|
|
- }
|
|
|
- return value;
|
|
|
- }, ' ');
|
|
|
-}
|
|
|
-
|
|
|
-function searchToObject() {
|
|
|
- // modified from https://stackoverflow.com/a/7090123/806777
|
|
|
- var pairs = location.search.slice(1).split('&');
|
|
|
- var obj = {};
|
|
|
-
|
|
|
- for (var i = 0; i < pairs.length; i++) {
|
|
|
- if (pairs[i] === '') {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- var pair = pairs[i].split('=');
|
|
|
-
|
|
|
- obj[decodeURIComponent(pair.shift())] = decodeURIComponent(pair.join('='));
|
|
|
- }
|
|
|
-
|
|
|
- return obj;
|
|
|
-}
|
|
|
-
|
|
|
-function jsonString(input) {
|
|
|
- var output = (input + '')
|
|
|
- .replace(/\n/g, '\\n')
|
|
|
- .replace(/\r/g, '\\r')
|
|
|
- .replace(/\t/g, '\\t')
|
|
|
- .replace(/\f/g, '\\f')
|
|
|
- .replace(/[\\"']/g, '\\$&')
|
|
|
- .replace(/\u0000/g, '\\0');
|
|
|
- return '"' + output + '"';
|
|
|
-}
|
|
|
-
|
|
|
-function getScrollSize() {
|
|
|
- var e = $activeOutputElem;
|
|
|
-
|
|
|
- return e.scrollHeight - e.clientHeight;
|
|
|
-}
|
|
|
-
|
|
|
-function getScrollPercent() {
|
|
|
- var size = getScrollSize();
|
|
|
-
|
|
|
- if (size <= 0) {
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- return $activeOutputElem.scrollTop / size;
|
|
|
-}
|
|
|
-
|
|
|
-function setScrollPercent(percent) {
|
|
|
- $activeOutputElem.scrollTop = percent * getScrollSize();
|
|
|
-}
|
|
|
-
|
|
|
-function updateLink() {
|
|
|
- var outputType = '';
|
|
|
- if ($outputTypeElem.value !== 'preview') {
|
|
|
- outputType = 'outputType=' + $outputTypeElem.value + '&';
|
|
|
- }
|
|
|
-
|
|
|
- $permalinkElem.href = '?' + outputType + 'text=' + encodeURIComponent($markdownElem.value)
|
|
|
- + '&options=' + encodeURIComponent($optionsElem.value)
|
|
|
- + '&version=' + encodeURIComponent($markedVerElem.value);
|
|
|
- history.replaceState('', document.title, $permalinkElem.href);
|
|
|
-}
|
|
|
-
|
|
|
-function updateVersion() {
|
|
|
- if (window.Worker) {
|
|
|
- handleInput();
|
|
|
- return Promise.resolve();
|
|
|
- }
|
|
|
- var promise;
|
|
|
- if (markedVersionCache[$markedVerElem.value]) {
|
|
|
- promise = Promise.resolve(markedVersionCache[$markedVerElem.value]);
|
|
|
- } else {
|
|
|
- promise = fetch(markedVersions[$markedVerElem.value])
|
|
|
- .then(function(res) { return res.text(); })
|
|
|
- .then(function(text) {
|
|
|
- markedVersionCache[$markedVerElem.value] = text;
|
|
|
- return text;
|
|
|
- });
|
|
|
- }
|
|
|
- return promise.then(function(text) {
|
|
|
- var script = document.createElement('script');
|
|
|
- script.textContent = text;
|
|
|
-
|
|
|
- $markedVer.parentNode.replaceChild(script, $markedVer);
|
|
|
- $markedVer = script;
|
|
|
- }).then(handleInput);
|
|
|
-}
|
|
|
-
|
|
|
-function checkForChanges() {
|
|
|
- if (inputDirty && $markedVerElem.value !== 'commit' && $markedVerElem.value !== 'pr' && (typeof marked !== 'undefined' || window.Worker)) {
|
|
|
- inputDirty = false;
|
|
|
-
|
|
|
- updateLink();
|
|
|
-
|
|
|
- var options = {};
|
|
|
- var optionsString = $optionsElem.value || '{}';
|
|
|
- try {
|
|
|
- var newOptions = JSON.parse(optionsString);
|
|
|
- options = newOptions;
|
|
|
- $optionsElem.classList.remove('error');
|
|
|
- } catch (err) {
|
|
|
- $optionsElem.classList.add('error');
|
|
|
- }
|
|
|
-
|
|
|
- var version = markedVersions[$markedVerElem.value];
|
|
|
- var markdown = $markdownElem.value;
|
|
|
- var hash = version + markdown + optionsString;
|
|
|
- if (lastInput !== hash) {
|
|
|
- lastInput = hash;
|
|
|
- if (window.Worker) {
|
|
|
- delayTime = 100;
|
|
|
- messageWorker({
|
|
|
- task: 'parse',
|
|
|
- version: version,
|
|
|
- markdown: markdown,
|
|
|
- options: options
|
|
|
- });
|
|
|
- } else {
|
|
|
- var startTime = new Date();
|
|
|
- var lexed = marked.lexer(markdown, options);
|
|
|
- var lexedList = [];
|
|
|
- for (var i = 0; i < lexed.length; i++) {
|
|
|
- var lexedLine = [];
|
|
|
- for (var j in lexed[i]) {
|
|
|
- lexedLine.push(j + ':' + jsonString(lexed[i][j]));
|
|
|
- }
|
|
|
- lexedList.push('{' + lexedLine.join(', ') + '}');
|
|
|
- }
|
|
|
- var parsed = marked.parser(lexed, options);
|
|
|
- var scrollPercent = getScrollPercent();
|
|
|
- setParsed(parsed, lexedList.join('\n'));
|
|
|
- setScrollPercent(scrollPercent);
|
|
|
- var endTime = new Date();
|
|
|
- delayTime = endTime - startTime;
|
|
|
- setResponseTime(delayTime);
|
|
|
- if (delayTime < 50) {
|
|
|
- delayTime = 50;
|
|
|
- } else if (delayTime > 500) {
|
|
|
- delayTime = 1000;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- checkChangeTimeout = window.setTimeout(checkForChanges, delayTime);
|
|
|
-}
|
|
|
-
|
|
|
-function setResponseTime(ms) {
|
|
|
- var amount = ms;
|
|
|
- var suffix = 'ms';
|
|
|
- if (ms > 1000 * 60 * 60) {
|
|
|
- amount = 'Too Long';
|
|
|
- suffix = '';
|
|
|
- } else if (ms > 1000 * 60) {
|
|
|
- amount = '>' + Math.floor(ms / (1000 * 60));
|
|
|
- suffix = 'm';
|
|
|
- } else if (ms > 1000) {
|
|
|
- amount = '>' + Math.floor(ms / 1000);
|
|
|
- suffix = 's';
|
|
|
- }
|
|
|
- $responseTimeElem.textContent = amount + suffix;
|
|
|
-}
|
|
|
-
|
|
|
-function setParsed(parsed, lexed) {
|
|
|
- try {
|
|
|
- $previewIframe.contentDocument.body.innerHTML = parsed;
|
|
|
- } catch (ex) {}
|
|
|
- $htmlElem.value = parsed;
|
|
|
- $lexerElem.value = lexed;
|
|
|
-}
|
|
|
-
|
|
|
-function messageWorker(message) {
|
|
|
- if (!markedWorker || markedWorker.working) {
|
|
|
- if (markedWorker) {
|
|
|
- clearTimeout(markedWorker.timeout);
|
|
|
- markedWorker.terminate();
|
|
|
- }
|
|
|
- markedWorker = new Worker('worker.js');
|
|
|
- markedWorker.onmessage = function(e) {
|
|
|
- clearTimeout(markedWorker.timeout);
|
|
|
- markedWorker.working = false;
|
|
|
- switch (e.data.task) {
|
|
|
- case 'defaults':
|
|
|
- setOptions(e.data.defaults);
|
|
|
- break;
|
|
|
- case 'parse':
|
|
|
- $previewElem.classList.remove('error');
|
|
|
- $htmlElem.classList.remove('error');
|
|
|
- $lexerElem.classList.remove('error');
|
|
|
- var scrollPercent = getScrollPercent();
|
|
|
- setParsed(e.data.parsed, e.data.lexed);
|
|
|
- setScrollPercent(scrollPercent);
|
|
|
- setResponseTime(e.data.time);
|
|
|
- break;
|
|
|
- }
|
|
|
- clearTimeout(checkChangeTimeout);
|
|
|
- delayTime = 10;
|
|
|
- checkForChanges();
|
|
|
- };
|
|
|
- markedWorker.onerror = markedWorker.onmessageerror = function(err) {
|
|
|
- clearTimeout(markedWorker.timeout);
|
|
|
- var error = 'There was an error in the Worker';
|
|
|
- if (err) {
|
|
|
- if (err.message) {
|
|
|
- error = err.message;
|
|
|
- } else {
|
|
|
- error = err;
|
|
|
- }
|
|
|
- }
|
|
|
- error = error.replace(/^Uncaught Error: /, '');
|
|
|
- $previewElem.classList.add('error');
|
|
|
- $htmlElem.classList.add('error');
|
|
|
- $lexerElem.classList.add('error');
|
|
|
- setParsed(error, error);
|
|
|
- setScrollPercent(0);
|
|
|
- };
|
|
|
- }
|
|
|
- if (message.task !== 'defaults') {
|
|
|
- markedWorker.working = true;
|
|
|
- workerTimeout(0);
|
|
|
- }
|
|
|
- markedWorker.postMessage(message);
|
|
|
-}
|
|
|
-
|
|
|
-function workerTimeout(seconds) {
|
|
|
- markedWorker.timeout = setTimeout(function() {
|
|
|
- seconds++;
|
|
|
- markedWorker.onerror('Marked has taken longer than ' + seconds + ' second' + (seconds > 1 ? 's' : '') + ' to respond...');
|
|
|
- workerTimeout(seconds);
|
|
|
- }, 1000);
|
|
|
-}
|