monkeeShark/src/client/pages/doc.vue

135 lines
2.4 KiB
Vue
Raw Normal View History

2020-02-06 16:20:04 +00:00
<template>
<div>
<portal to="icon"><fa :icon="faFileAlt"/></portal>
<portal to="title">{{ title }}</portal>
<main class="_card">
<div class="_content">
2020-02-06 17:38:02 +00:00
<div v-html="body" class="qyqbqfal"></div>
2020-02-06 16:20:04 +00:00
</div>
</main>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { faFileAlt } from '@fortawesome/free-solid-svg-icons'
import MarkdownIt from 'markdown-it';
2020-02-06 17:38:02 +00:00
import { url, lang } from '../config';
2020-02-06 16:20:04 +00:00
2020-02-06 17:38:02 +00:00
const markdown = MarkdownIt({
html: true
});
2020-02-06 16:20:04 +00:00
export default Vue.extend({
metaInfo() {
return {
title: this.title,
};
},
2020-02-06 17:38:02 +00:00
props: {
doc: {
type: String,
required: true
}
2020-02-06 16:20:04 +00:00
},
watch: {
2020-02-06 17:38:02 +00:00
doc: {
handler() {
this.fetchDoc();
},
immediate: true,
2020-02-06 16:20:04 +00:00
}
},
data() {
return {
faFileAlt,
title: '',
body: '',
2020-02-06 17:38:02 +00:00
markdown: '',
2020-02-06 16:20:04 +00:00
}
},
methods: {
2020-02-06 17:38:02 +00:00
fetchDoc() {
fetch(`${url}/assets/docs/${this.doc}.${lang}.md`).then(res => res.text()).then(md => {
this.parse(md);
});
},
parse(md: string) {
2020-02-06 16:20:04 +00:00
// markdown の全容をパースする
2020-02-06 17:38:02 +00:00
const parsed = markdown.parse(md, {});
if (parsed.length === 0) return;
2020-02-06 16:20:04 +00:00
2020-02-06 17:38:02 +00:00
const buf = [...parsed];
2020-02-06 16:20:04 +00:00
const headingTokens = [];
let headingStart = 0;
// もっとも上にある見出しを抽出する
while (buf[0].type !== 'heading_open') {
buf.shift();
headingStart++;
}
buf.shift();
while (buf[0].type as string !== 'heading_close') {
const token = buf.shift();
if (token) {
headingTokens.push(token);
}
}
// 抽出した見出しを除く部分をbodyとして抽出する
2020-02-06 17:38:02 +00:00
const bodyTokens = [...parsed];
2020-02-06 16:20:04 +00:00
bodyTokens.splice(headingStart, headingTokens.length + 2);
// 各々レンダーする
this.title = markdown.renderer.render(headingTokens, {}, {});
this.body = markdown.renderer.render(bodyTokens, {}, {});
}
}
});
</script>
2020-02-06 17:38:02 +00:00
<style lang="scss" scoped>
.qyqbqfal {
> *:first-child {
margin-top: 0;
}
> *:last-child {
margin-bottom: 0;
}
::v-deep h2 {
font-size: 1.25em;
padding: 0 0 0.5em 0;
border-bottom: solid 1px var(--divider);
}
::v-deep table {
width: 100%;
max-width: 100%;
overflow: auto;
}
::v-deep kbd.group {
display: inline-block;
padding: 2px;
border: 1px solid var(--divider);
border-radius: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}
::v-deep kbd.key {
display: inline-block;
padding: 6px 8px;
border: solid 1px var(--divider);
border-radius: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}
}
</style>