diff options
Diffstat (limited to 'viewer/src')
-rw-r--r-- | viewer/src/components/LdInformation.vue | 15 | ||||
-rw-r--r-- | viewer/src/components/async/Markdown.vue | 123 | ||||
-rw-r--r-- | viewer/src/components/async/index.ts | 4 | ||||
-rw-r--r-- | viewer/src/main.ts | 9 | ||||
-rw-r--r-- | viewer/src/plugins/index.ts | 8 | ||||
-rw-r--r-- | viewer/src/services/fetchWithCheck.ts | 7 |
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"> |
29 | import { Item } from "@/@types/gallery"; | 29 | import { Item } from "@/@types/gallery"; |
30 | import marked from "marked"; | 30 | import { Markdown } from "@/components/async"; |
31 | import { Component, Prop, Vue } from "vue-property-decorator"; | 31 | import { Component, Prop, Vue } from "vue-property-decorator"; |
32 | 32 | ||
33 | @Component | 33 | @Component({ |
34 | components: { | ||
35 | Markdown, | ||
36 | }, | ||
37 | }) | ||
34 | export default class LdInformation extends Vue { | 38 | export 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"> | ||
26 | import marked from "marked"; | ||
27 | import { Component, Prop, Vue } from "vue-property-decorator"; | ||
28 | |||
29 | @Component | ||
30 | export 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 | |||
4 | export 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 @@ | |||
20 | import "@/assets/scss/global.scss"; | 20 | import "@/assets/scss/global.scss"; |
21 | import "@/assets/scss/scrollbar.scss"; | 21 | import "@/assets/scss/scrollbar.scss"; |
22 | import "@/assets/scss/transition.scss"; | 22 | import "@/assets/scss/transition.scss"; |
23 | import { MainLayout } from "@/plugins"; | ||
23 | import i18n from "@/plugins/i18n"; | 24 | import i18n from "@/plugins/i18n"; |
24 | import router from "@/plugins/router"; | 25 | import router from "@/plugins/router"; |
25 | import store from "@/store"; | 26 | import store from "@/store"; |
26 | import Vue from "vue"; | 27 | import Vue from "vue"; |
27 | Vue.config.productionTip = false; | ||
28 | 28 | ||
29 | import(/* webpackChunkName: "ui" */ "@/plugins/buefy"); | 29 | Vue.config.productionTip = false; |
30 | import(/* webpackChunkName: "ui" */ "@/components"); | ||
31 | import(/* webpackChunkName: "ui" */ "@/plugins/lazyimage"); | ||
32 | import(/* webpackChunkName: "ui" */ "@/plugins/dragscroll"); | ||
33 | import(/* webpackChunkName: "ui" */ "@/plugins/fontawesome"); | ||
34 | const MainLayout = () => import(/* webpackChunkName: "ui" */ "@/views/MainLayout.vue"); | ||
35 | 30 | ||
36 | declare module "vue/types/vue" { | 31 | declare 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 @@ | |||
1 | export 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 @@ | |||
1 | export 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 | } | ||