|
| 1 | +<template> |
| 2 | + <div> |
| 3 | + <div v-if="loading">Loading...</div> |
| 4 | + <div class="uk-alert uk-alert-danger" v-if="error">{{ error }}</div> |
| 5 | + <div ref="page"></div> |
| 6 | + </div> |
| 7 | +</template> |
| 8 | + |
| 9 | +<script> |
| 10 | +
|
| 11 | +import $ from 'jquery'; |
| 12 | +import { escape } from 'he' |
| 13 | +
|
| 14 | +export default { |
| 15 | +
|
| 16 | + data() { |
| 17 | + return { |
| 18 | + loading: false, |
| 19 | + page: null, |
| 20 | + error: null, |
| 21 | + cache: {}, |
| 22 | + ids: {}, |
| 23 | + test: 123 |
| 24 | + } |
| 25 | + }, |
| 26 | +
|
| 27 | + mounted() { |
| 28 | + this.$page = $(this.$refs.page); |
| 29 | + this.loadPage(this.$route.params.page); |
| 30 | + }, |
| 31 | +
|
| 32 | + watch: { |
| 33 | + $route () { |
| 34 | + this.loadPage(this.$route.params.page); |
| 35 | + } |
| 36 | + }, |
| 37 | +
|
| 38 | + methods: { |
| 39 | +
|
| 40 | + loadPage(page) { |
| 41 | +
|
| 42 | + scrollTo(0, 0); |
| 43 | +
|
| 44 | + this.loading = true; |
| 45 | + this.$page.html(''); |
| 46 | + this.error = null; |
| 47 | + this.ids = {}; |
| 48 | +
|
| 49 | + var defer = $.Deferred(); |
| 50 | +
|
| 51 | + defer.promise().done(content => { |
| 52 | + this.loading = false; |
| 53 | + this.$page.html(content); |
| 54 | + Vue.nextTick(() => { |
| 55 | +
|
| 56 | + $('pre code').each((i, block) => { |
| 57 | + hljs.highlightBlock(block); |
| 58 | + }); |
| 59 | +
|
| 60 | + $('[href="#"]', this.$el).on('click', e => { |
| 61 | + e.preventDefault(); |
| 62 | + }); |
| 63 | +
|
| 64 | + this.createIds(); |
| 65 | +
|
| 66 | + if (location.hash && $(location.hash.length)) { |
| 67 | + scrollTo(0, $(location.hash).offset().top); |
| 68 | + } |
| 69 | + }); |
| 70 | + }).fail(() => { |
| 71 | + this.loading = false; |
| 72 | + this.error = 'Failed loading page'; |
| 73 | + }); |
| 74 | +
|
| 75 | + if (this.cache[page]) { |
| 76 | + defer.resolve(this.cache[page]); |
| 77 | + return; |
| 78 | + } |
| 79 | +
|
| 80 | + $.get(`pages/${page}.md`, {nc: Math.random()}).done(content => { |
| 81 | +
|
| 82 | + this.parse(content, (err, content) => { |
| 83 | +
|
| 84 | + if (err) { |
| 85 | + defer.reject(err); |
| 86 | + return; |
| 87 | + } |
| 88 | +
|
| 89 | + this.cache[page] = content; |
| 90 | + defer.resolve(content) |
| 91 | + }); |
| 92 | +
|
| 93 | + }).fail(err => reject(err)); |
| 94 | + }, |
| 95 | +
|
| 96 | + parse(markdown, cb) { |
| 97 | +
|
| 98 | + var renderer = new marked.Renderer({langPrefix: 'lang-'}); |
| 99 | + var base = new marked.Renderer({langPrefix: 'lang-'}); |
| 100 | + var slugify = text => text.toLowerCase().replace(/ /g,'-').replace(/[^\w-]+/g,''); |
| 101 | + var modal = (href, text) => { |
| 102 | + var slug = 'modal-'+slugify(text); |
| 103 | + return `<a href="#${slug}" uk-toggle><p class="uk-margin-large-bottom"><img src="${href}" alt="${text}"></p></a> |
| 104 | + <div id="${slug}" class="uk-modal-full" uk-modal> |
| 105 | + <div class="uk-modal-dialog uk-flex uk-flex-center uk-flex-middle uk-height-viewport"> |
| 106 | + <button class="uk-modal-close-full" type="button" uk-close></button> |
| 107 | + <img src="${href}" alt="${text}"> |
| 108 | + </div></div>`; |
| 109 | + }; |
| 110 | + var example = code => { |
| 111 | + return `<ul uk-tab> |
| 112 | + <li><a href="#">Preview</a></li> |
| 113 | + <li><a href="#">Markup</a></li> |
| 114 | + </ul> |
| 115 | + <ul class="uk-switcher uk-margin"> |
| 116 | + <li>${code}</li> |
| 117 | + <li><pre><code class="lang-html">${escape(code)}</code></pre> |
| 118 | + </li> |
| 119 | + <li></li> |
| 120 | + </ul>`; |
| 121 | + } |
| 122 | +
|
| 123 | + renderer.list = text => `<ul class="uk-list uk-list-bullet">${text}</ul>`; |
| 124 | + renderer.image = (href, title, text) => href.match(/modal$/) ? modal(href, text) : base.image(href, title, text); |
| 125 | + renderer.link = (href, title, text) => href.match(/\.md/) ? base.link(href.replace(/\.md$/, ''), title, text) : base.link(href, title, text); |
| 126 | + renderer.code = (code, lang, escaped) => lang == 'example' ? example(code) : '<div class="uk-margin-medium">'+base.code(code, lang, escaped)+'</div>'; |
| 127 | + renderer.hr = () => `<hr class="uk-margin-large">`; |
| 128 | + renderer.table = (header, body) => `<div class="uk-overflow-auto"><table class="uk-table uk-table-striped"><thead>${header}</thead><tbody>${body}</tbody></table></div>`; |
| 129 | + renderer.heading = (text, level) => { |
| 130 | + return level == 2 |
| 131 | + ? `<h${level} class="uk-position-relative uk-h${level>1 ? level+1 : level}"><a class="uk-text-muted uk-link-muted uk-position-absolute" href="#${text.toLowerCase().replace(/ /g,"-")}" style="transform:translateX(-30px)">#</a>${text}</h${level}>` |
| 132 | + : `<h${level} class="uk-h${level>1 ? level+1 : level}">${text}</h${level}>`; |
| 133 | + } |
| 134 | +
|
| 135 | + return marked(markdown, {renderer}, cb); |
| 136 | + }, |
| 137 | +
|
| 138 | + createIds () { |
| 139 | +
|
| 140 | + let $this = this; |
| 141 | +
|
| 142 | + this.$parent.ids = {}; |
| 143 | +
|
| 144 | + $('h1,h2', this.$el).each(function () { |
| 145 | +
|
| 146 | + let $element = $(this), text = $(this).text().replace('#', ''), id = text.toLowerCase().replace(/ /g, '-'); |
| 147 | +
|
| 148 | + $element.attr('id', id); |
| 149 | +
|
| 150 | + if ($element.is('h2')) { |
| 151 | + $this.$parent.ids[text] = id; |
| 152 | + } |
| 153 | + }); |
| 154 | +
|
| 155 | + } |
| 156 | + } |
| 157 | +
|
| 158 | +} |
| 159 | +
|
| 160 | +</script> |
0 commit comments