aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--viewer/src/components/LdInformation.vue15
-rw-r--r--viewer/src/components/async/Markdown.vue123
-rw-r--r--viewer/src/components/async/index.ts4
-rw-r--r--viewer/src/main.ts9
-rw-r--r--viewer/src/plugins/index.ts8
-rw-r--r--viewer/src/services/fetchWithCheck.ts7
6 files changed, 151 insertions, 15 deletions
diff --git a/viewer/src/components/LdInformation.vue b/viewer/src/components/LdInformation.vue
index b161485..68e1817 100644
--- a/viewer/src/components/LdInformation.vue
+++ b/viewer/src/components/LdInformation.vue
@@ -21,16 +21,20 @@
21 <div v-if="item" class="flex-column" :class="$style.infopanel"> 21 <div v-if="item" class="flex-column" :class="$style.infopanel">
22 <div v-if="item.title" :class="$style.title">{{ item.title }}</div> 22 <div v-if="item.title" :class="$style.title">{{ item.title }}</div>
23 <time v-if="item.datetime" :datetime="item.datetime" :class="$style.datetime">{{ formatDate }}</time> 23 <time v-if="item.datetime" :datetime="item.datetime" :class="$style.datetime">{{ formatDate }}</time>
24 <div v-if="item.description" :class="$style.description" v-html="formatDescription" /> 24 <Markdown v-if="item.description" :class="$style.description" :markdown="item.description" />
25 </div> 25 </div>
26</template> 26</template>
27 27
28<script lang="ts"> 28<script lang="ts">
29import { Item } from "@/@types/gallery"; 29import { Item } from "@/@types/gallery";
30import marked from "marked"; 30import { Markdown } from "@/components/async";
31import { Component, Prop, Vue } from "vue-property-decorator"; 31import { Component, Prop, Vue } from "vue-property-decorator";
32 32
33@Component 33@Component({
34 components: {
35 Markdown,
36 },
37})
34export default class LdInformation extends Vue { 38export default class LdInformation extends Vue {
35 @Prop({ required: true }) readonly item!: Item; 39 @Prop({ required: true }) readonly item!: Item;
36 40
@@ -39,11 +43,6 @@ export default class LdInformation extends Vue {
39 const time = this.item.datetime.substr(11, 5); 43 const time = this.item.datetime.substr(11, 5);
40 return `${date} ${time}`; 44 return `${date} ${time}`;
41 } 45 }
42
43 get formatDescription() {
44 if (!this.item.description) return "";
45 return marked(this.item.description);
46 }
47} 46}
48</script> 47</script>
49 48
diff --git a/viewer/src/components/async/Markdown.vue b/viewer/src/components/async/Markdown.vue
new file mode 100644
index 0000000..c4e282b
--- /dev/null
+++ b/viewer/src/components/async/Markdown.vue
@@ -0,0 +1,123 @@
1<!--
2-- ldgallery - A static generator which turns a collection of tagged
3-- pictures into a searchable web gallery.
4--
5-- Copyright (C) 2021 Guillaume FOUET
6--
7-- This program is free software: you can redistribute it and/or modify
8-- it under the terms of the GNU Affero General Public License as
9-- published by the Free Software Foundation, either version 3 of the
10-- License, or (at your option) any later version.
11--
12-- This program is distributed in the hope that it will be useful,
13-- but WITHOUT ANY WARRANTY; without even the implied warranty of
14-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15-- GNU Affero General Public License for more details.
16--
17-- You should have received a copy of the GNU Affero General Public License
18-- along with this program. If not, see <https://www.gnu.org/licenses/>.
19-->
20
21<template>
22 <div :class="$style.markdown" v-html="html" />
23</template>
24
25<script lang="ts">
26import marked from "marked";
27import { Component, Prop, Vue } from "vue-property-decorator";
28
29@Component
30export default class Markdown extends Vue {
31 @Prop({ required: true }) readonly markdown!: string;
32
33 get html(): string {
34 return marked(this.markdown);
35 }
36}
37</script>
38
39<style lang="scss" module>
40.markdown {
41 line-height: 1.7;
42 word-wrap: break-word;
43
44 a {
45 color: #9bcdff;
46 text-decoration: none;
47 }
48
49 hr {
50 background-color: #666;
51 }
52
53 p,
54 blockquote,
55 ul,
56 ol,
57 dl,
58 table,
59 pre {
60 margin: 15px 0;
61 }
62
63 ul,
64 ol {
65 padding-left: 30px;
66 }
67
68 h1 {
69 border-bottom: 1px solid #888;
70 font-size: 2.5em;
71 }
72
73 h2 {
74 border-bottom: 1px solid #666;
75 font-size: 2em;
76 }
77
78 h3 {
79 font-size: 1.5em;
80 }
81
82 h4 {
83 font-size: 1.2em;
84 }
85
86 h5 {
87 font-size: 1em;
88 }
89
90 h6 {
91 color: #777;
92 font-size: 1em;
93 }
94
95 h1,
96 h2,
97 h3,
98 h4,
99 h5,
100 h6 {
101 font-weight: bold;
102 margin: 1em 0 15px 0;
103 }
104
105 h1 + p,
106 h2 + p,
107 h3 + p {
108 margin-top: 10px;
109 }
110
111 pre {
112 color: white;
113 background-color: #2e4049;
114 }
115
116 code {
117 @extend pre;
118 font-family: Consolas, "Liberation Mono", Courier, monospace;
119 font-size: 0.8em;
120 white-space: pre;
121 }
122}
123</style>
diff --git a/viewer/src/components/async/index.ts b/viewer/src/components/async/index.ts
new file mode 100644
index 0000000..5a7d9a6
--- /dev/null
+++ b/viewer/src/components/async/index.ts
@@ -0,0 +1,4 @@
1// Declare async constants for internal components
2// Their name can't start with 'Ld'
3
4export const Markdown = () => import(/* webpackChunkName: "markdown" */ "./Markdown.vue");
diff --git a/viewer/src/main.ts b/viewer/src/main.ts
index cccb37b..d0ee3af 100644
--- a/viewer/src/main.ts
+++ b/viewer/src/main.ts
@@ -20,18 +20,13 @@
20import "@/assets/scss/global.scss"; 20import "@/assets/scss/global.scss";
21import "@/assets/scss/scrollbar.scss"; 21import "@/assets/scss/scrollbar.scss";
22import "@/assets/scss/transition.scss"; 22import "@/assets/scss/transition.scss";
23import { MainLayout } from "@/plugins";
23import i18n from "@/plugins/i18n"; 24import i18n from "@/plugins/i18n";
24import router from "@/plugins/router"; 25import router from "@/plugins/router";
25import store from "@/store"; 26import store from "@/store";
26import Vue from "vue"; 27import Vue from "vue";
27Vue.config.productionTip = false;
28 28
29import(/* webpackChunkName: "ui" */ "@/plugins/buefy"); 29Vue.config.productionTip = false;
30import(/* webpackChunkName: "ui" */ "@/components");
31import(/* webpackChunkName: "ui" */ "@/plugins/lazyimage");
32import(/* webpackChunkName: "ui" */ "@/plugins/dragscroll");
33import(/* webpackChunkName: "ui" */ "@/plugins/fontawesome");
34const MainLayout = () => import(/* webpackChunkName: "ui" */ "@/views/MainLayout.vue");
35 30
36declare module "vue/types/vue" { 31declare module "vue/types/vue" {
37 interface Vue { 32 interface Vue {
diff --git a/viewer/src/plugins/index.ts b/viewer/src/plugins/index.ts
new file mode 100644
index 0000000..1555882
--- /dev/null
+++ b/viewer/src/plugins/index.ts
@@ -0,0 +1,8 @@
1export const MainLayout = () =>
2 Promise.all([
3 import(/* webpackChunkName: "ui" */ "@/plugins/buefy"),
4 import(/* webpackChunkName: "ui" */ "@/components"),
5 import(/* webpackChunkName: "ui" */ "@/plugins/lazyimage"),
6 import(/* webpackChunkName: "ui" */ "@/plugins/dragscroll"),
7 import(/* webpackChunkName: "ui" */ "@/plugins/fontawesome"),
8 ]).then(() => import(/* webpackChunkName: "ui" */ "@/views/MainLayout.vue"));
diff --git a/viewer/src/services/fetchWithCheck.ts b/viewer/src/services/fetchWithCheck.ts
new file mode 100644
index 0000000..e84e8b6
--- /dev/null
+++ b/viewer/src/services/fetchWithCheck.ts
@@ -0,0 +1,7 @@
1export default class FetchWithCheck {
2 static async get(url: RequestInfo): Promise<Response> {
3 const response = await fetch(url);
4 if (!response.ok) throw new Error(`${response.status}: ${response.statusText}`);
5 return response;
6 }
7}