slidev-theme-gtlabo 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Citation.vue +38 -20
- package/components/CitationListPage.vue +14 -7
- package/components/TableOfContents.vue +2 -2
- package/layouts/cover.vue +217 -35
- package/package.json +1 -1
- package/uno.config.ts +2 -2
package/components/Citation.vue
CHANGED
|
@@ -37,11 +37,33 @@ const props = defineProps({
|
|
|
37
37
|
}
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
//
|
|
40
|
+
// グローバル引用管理の初期化
|
|
41
41
|
if (!window.citationManager) {
|
|
42
42
|
window.citationManager = {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
citations: new Map(), // id -> { number, data, formatted }
|
|
44
|
+
citationKeys: Object.keys(citations), // frontmatterのキーの順番を保持
|
|
45
|
+
initialized: false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// frontmatterの順番でcitation番号を事前に割り当て
|
|
50
|
+
const initializeCitations = () => {
|
|
51
|
+
if (!window.citationManager.initialized) {
|
|
52
|
+
window.citationManager.citationKeys = Object.keys(citations)
|
|
53
|
+
|
|
54
|
+
window.citationManager.citationKeys.forEach((key, index) => {
|
|
55
|
+
if (!window.citationManager.citations.has(key)) {
|
|
56
|
+
const data = citations[key]
|
|
57
|
+
const newCitation = {
|
|
58
|
+
number: index + 1, // 1から開始
|
|
59
|
+
data: data,
|
|
60
|
+
formatted: formatCitation(data)
|
|
61
|
+
}
|
|
62
|
+
window.citationManager.citations.set(key, newCitation)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
window.citationManager.initialized = true
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
69
|
|
|
@@ -59,24 +81,21 @@ const citationData = computed(() => {
|
|
|
59
81
|
return data
|
|
60
82
|
})
|
|
61
83
|
|
|
62
|
-
//
|
|
84
|
+
// 引用番号を取得
|
|
63
85
|
const citationNumber = computed(() => {
|
|
64
86
|
if (!citationData.value) {
|
|
65
87
|
return '?'
|
|
66
88
|
}
|
|
67
89
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
number: window.citationManager.counter,
|
|
71
|
-
data: citationData.value,
|
|
72
|
-
formatted: formatCitation(citationData.value)
|
|
73
|
-
}
|
|
74
|
-
window.citationManager.citations.set(props.id, newCitation)
|
|
75
|
-
window.citationManager.counter++
|
|
76
|
-
}
|
|
90
|
+
// 初期化を確実に実行
|
|
91
|
+
initializeCitations()
|
|
77
92
|
|
|
78
93
|
const citation = window.citationManager.citations.get(props.id)
|
|
79
|
-
|
|
94
|
+
if (citation) {
|
|
95
|
+
return citation.number
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return '?'
|
|
80
99
|
})
|
|
81
100
|
|
|
82
101
|
// フォーマットされた引用テキスト
|
|
@@ -96,7 +115,6 @@ const formattedCitation = computed(() => {
|
|
|
96
115
|
// 引用を表示すべきかどうか
|
|
97
116
|
const shouldShowCitation = computed(() => {
|
|
98
117
|
const shouldShow = isMounted.value && citationData.value !== null
|
|
99
|
-
|
|
100
118
|
return shouldShow
|
|
101
119
|
})
|
|
102
120
|
|
|
@@ -158,30 +176,30 @@ const formatCitation = (data) => {
|
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
const formatted = citation || '引用情報が不完全です'
|
|
161
|
-
|
|
162
179
|
return formatted
|
|
163
180
|
}
|
|
164
181
|
|
|
165
182
|
// 全体のグローバル状態をデバッグ出力
|
|
166
183
|
const debugGlobalState = () => {
|
|
184
|
+
// デバッグ用(必要に応じてコメントアウト)
|
|
167
185
|
}
|
|
168
186
|
|
|
169
187
|
// コンポーネントのマウント時
|
|
170
188
|
onMounted(() => {
|
|
171
|
-
|
|
172
189
|
isMounted.value = true
|
|
173
190
|
|
|
191
|
+
// 初期化を確実に実行
|
|
192
|
+
initializeCitations()
|
|
193
|
+
|
|
174
194
|
if (citationData.value) {
|
|
175
|
-
//
|
|
195
|
+
// 引用番号を取得(副作用でglobal stateに保存される)
|
|
176
196
|
const _ = citationNumber.value
|
|
177
197
|
debugGlobalState()
|
|
178
|
-
} else {
|
|
179
198
|
}
|
|
180
199
|
})
|
|
181
200
|
|
|
182
201
|
// コンポーネントのアンマウント時
|
|
183
202
|
onUnmounted(() => {
|
|
184
|
-
|
|
185
203
|
isMounted.value = false
|
|
186
204
|
debugGlobalState()
|
|
187
205
|
})
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
:key="citation.key"
|
|
18
18
|
class="citation-item border-l-2 border-sky-400 pl-3 py-1"
|
|
19
19
|
>
|
|
20
|
-
<!--
|
|
20
|
+
<!-- 引用番号(frontmatterの順番に基づく) -->
|
|
21
21
|
<div class="text-sm font-semibold text-sky-700 mb-1">
|
|
22
|
-
[{{ citation.
|
|
22
|
+
[{{ citation.number }}]
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
25
|
<!-- 引用情報 -->
|
|
@@ -164,19 +164,23 @@ const props = defineProps({
|
|
|
164
164
|
// 表示順序
|
|
165
165
|
sortBy: {
|
|
166
166
|
type: String,
|
|
167
|
-
default: '
|
|
167
|
+
default: 'frontmatter', // 'frontmatter', 'key', 'author', 'year' など
|
|
168
168
|
}
|
|
169
169
|
})
|
|
170
170
|
|
|
171
|
-
//
|
|
171
|
+
// 参考文献リストを生成(frontmatterの順番を維持)
|
|
172
172
|
const citationsList = computed(() => {
|
|
173
173
|
if (!citations || typeof citations !== 'object') {
|
|
174
174
|
return []
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
// frontmatterの記述順でキーを取得
|
|
178
|
+
const originalKeys = Object.keys(citations)
|
|
179
|
+
|
|
180
|
+
const list = originalKeys.map((key, index) => ({
|
|
178
181
|
key,
|
|
179
|
-
data: citations[key]
|
|
182
|
+
data: citations[key],
|
|
183
|
+
number: index + 1 // frontmatterの順番に基づく番号
|
|
180
184
|
}))
|
|
181
185
|
|
|
182
186
|
// ソート処理
|
|
@@ -194,8 +198,11 @@ const citationsList = computed(() => {
|
|
|
194
198
|
return yearB - yearA // 降順(新しい順)
|
|
195
199
|
})
|
|
196
200
|
case 'key':
|
|
197
|
-
default:
|
|
198
201
|
return list.sort((a, b) => a.key.localeCompare(b.key))
|
|
202
|
+
case 'frontmatter':
|
|
203
|
+
default:
|
|
204
|
+
// frontmatterの順番を維持(デフォルト)
|
|
205
|
+
return list
|
|
199
206
|
}
|
|
200
207
|
})
|
|
201
208
|
|
|
@@ -269,8 +269,8 @@ const sizeConfigs = {
|
|
|
269
269
|
columns: 2,
|
|
270
270
|
headerPadding: 'pt-14 pb-8 px-10',
|
|
271
271
|
headerTitle: 'text-5xl',
|
|
272
|
-
mainPadding: 'px-
|
|
273
|
-
gridGap: 'gap-x-
|
|
272
|
+
mainPadding: 'px-6 py-40',
|
|
273
|
+
gridGap: 'gap-x-12 gap-y-2',
|
|
274
274
|
chapterNumber: 'text-6xl',
|
|
275
275
|
chapterTitle: 'text-2xl',
|
|
276
276
|
chapterHeader: 'mb-4',
|
package/layouts/cover.vue
CHANGED
|
@@ -1,33 +1,54 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="slidev-layout cover relative overflow-hidden
|
|
3
|
-
<!--
|
|
4
|
-
<div
|
|
5
|
-
|
|
2
|
+
<div class="slidev-layout cover relative overflow-hidden animated-gradient">
|
|
3
|
+
<!-- ランダムに動く大きな円形要素(右上) -->
|
|
4
|
+
<div
|
|
5
|
+
ref="circle1"
|
|
6
|
+
class="absolute -right-32 -top-32 w-96 h-96 bg-sky-300/70 rounded-full transition-all duration-[3000ms] ease-in-out"
|
|
7
|
+
:style="circleStyles[0]"
|
|
8
|
+
/>
|
|
9
|
+
<div
|
|
10
|
+
ref="circle2"
|
|
11
|
+
class="absolute right-8 top-24 w-64 h-64 bg-sky-400/60 rounded-full transition-all duration-[4000ms] ease-in-out"
|
|
12
|
+
:style="circleStyles[1]"
|
|
13
|
+
/>
|
|
6
14
|
|
|
7
|
-
<!--
|
|
8
|
-
<div
|
|
9
|
-
|
|
15
|
+
<!-- ランダムに動く左下の三角形要素 -->
|
|
16
|
+
<div
|
|
17
|
+
class="absolute left-16 bottom-16 w-0 h-0 border-l-48 border-r-48 border-b-80 border-transparent border-b-sky-400/50 transition-all duration-[3500ms] ease-in-out"
|
|
18
|
+
:style="triangleStyles[0]"
|
|
19
|
+
/>
|
|
20
|
+
<div
|
|
21
|
+
class="absolute left-32 bottom-32 w-0 h-0 border-l-32 border-r-32 border-b-56 border-transparent border-b-sky-500/55 transition-all duration-[4500ms] ease-in-out"
|
|
22
|
+
:style="triangleStyles[1]"
|
|
23
|
+
/>
|
|
10
24
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<div
|
|
17
|
-
|
|
25
|
+
<!-- ランダムに動く右下の斜線要素 -->
|
|
26
|
+
<div
|
|
27
|
+
class="absolute right-25 bottom-5 space-y-8 transition-all duration-[5000ms] ease-in-out"
|
|
28
|
+
:style="linesStyle"
|
|
29
|
+
>
|
|
30
|
+
<div
|
|
31
|
+
v-for="(width, index) in lineWidths"
|
|
32
|
+
:key="index"
|
|
33
|
+
class="h-3 rounded-md bg-sky-500/70 transition-all duration-[2000ms] ease-in-out"
|
|
34
|
+
:style="{ width: `${width}px` }"
|
|
35
|
+
/>
|
|
18
36
|
</div>
|
|
19
37
|
|
|
20
|
-
<!--
|
|
21
|
-
<div
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<div
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
<!-- ランダムに動く左上の円形グリッド -->
|
|
39
|
+
<div
|
|
40
|
+
class="absolute left-16 top-16 grid grid-cols-3 gap-3 opacity-60 rotating-grid"
|
|
41
|
+
:style="gridStyle"
|
|
42
|
+
>
|
|
43
|
+
<div
|
|
44
|
+
v-for="(dot, index) in dots"
|
|
45
|
+
:key="index"
|
|
46
|
+
:class="[
|
|
47
|
+
'w-8 h-8 rounded-full transition-all duration-[2500ms] ease-in-out',
|
|
48
|
+
dot.filled ? 'bg-sky-600' : 'border-2 border-sky-700'
|
|
49
|
+
]"
|
|
50
|
+
:style="dot.style"
|
|
51
|
+
/>
|
|
31
52
|
</div>
|
|
32
53
|
|
|
33
54
|
<!-- メインコンテンツ -->
|
|
@@ -38,10 +59,10 @@
|
|
|
38
59
|
{{ $slidev.configs.meetingName }}
|
|
39
60
|
</div>
|
|
40
61
|
|
|
41
|
-
<!--
|
|
62
|
+
<!-- メインタイトル -->
|
|
42
63
|
<div
|
|
43
64
|
:class="[
|
|
44
|
-
'font-bold text-slate-900 leading-tight',
|
|
65
|
+
'font-bold text-slate-900 leading-tight ',
|
|
45
66
|
getTitleSizeClass($slidev.configs.titleSize || 'large')
|
|
46
67
|
]"
|
|
47
68
|
>
|
|
@@ -59,14 +80,24 @@
|
|
|
59
80
|
</div>
|
|
60
81
|
|
|
61
82
|
<!-- 著者情報 -->
|
|
62
|
-
<div class="space-y-
|
|
63
|
-
<div class="
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
<div class="space-y-4">
|
|
84
|
+
<div class="flex flex-col items-end justify-between w-full w-full px-20">
|
|
85
|
+
<div class="text-2xl font-semibold text-slate-800 ">
|
|
86
|
+
{{ $slidev.configs.author.affiliation }}<span class="text-sky-600 ml-2">*</span>{{ $slidev.configs.author.name }}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<!-- 共著者 (存在する場合) -->
|
|
90
|
+
<div v-if="coAuthors.length > 0" class="space-y-1 flex flex-col items-end">
|
|
91
|
+
<div
|
|
92
|
+
v-for="(coAuthor, index) in coAuthors"
|
|
93
|
+
:key="index"
|
|
94
|
+
class="text-2xl font-semibold text-slate-800"
|
|
95
|
+
>
|
|
96
|
+
<span class="mr-2"> {{ coAuthor.affiliation }}</span> {{ coAuthor.name }}
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
68
99
|
</div>
|
|
69
|
-
|
|
100
|
+
|
|
70
101
|
<div class="text-xl font-semibold text-slate-700">
|
|
71
102
|
{{ $slidev.configs.date }}
|
|
72
103
|
</div>
|
|
@@ -82,6 +113,11 @@
|
|
|
82
113
|
</template>
|
|
83
114
|
|
|
84
115
|
<script setup>
|
|
116
|
+
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
|
117
|
+
import { useSlideContext } from '@slidev/client'
|
|
118
|
+
|
|
119
|
+
const { $slidev } = useSlideContext()
|
|
120
|
+
|
|
85
121
|
// タイトルサイズのクラスを返す関数
|
|
86
122
|
function getTitleSizeClass(size) {
|
|
87
123
|
const sizeMap = {
|
|
@@ -94,4 +130,150 @@ function getTitleSizeClass(size) {
|
|
|
94
130
|
|
|
95
131
|
return sizeMap[size] || sizeMap['large']
|
|
96
132
|
}
|
|
97
|
-
|
|
133
|
+
|
|
134
|
+
// 共著者リストを取得
|
|
135
|
+
const coAuthors = computed(() => {
|
|
136
|
+
const configs = $slidev.configs
|
|
137
|
+
if (!configs || !configs.coAuthors || !Array.isArray(configs.coAuthors)) {
|
|
138
|
+
return []
|
|
139
|
+
}
|
|
140
|
+
console.log(configs.coAuthors)
|
|
141
|
+
// 最大4人まで
|
|
142
|
+
return configs.coAuthors.slice(0, 4)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// ランダムな値を生成する関数
|
|
146
|
+
const randomRange = (min, max) => Math.random() * (max - min) + min
|
|
147
|
+
|
|
148
|
+
// 初期状態でランダムな位置を設定
|
|
149
|
+
const circleStyles = ref([
|
|
150
|
+
{ transform: `translate(${randomRange(-15, 15)}px, ${randomRange(-15, 15)}px) rotate(${randomRange(-5, 5)}deg)` },
|
|
151
|
+
{ transform: `translate(${randomRange(-20, 20)}px, ${randomRange(-20, 20)}px) rotate(${randomRange(-8, 8)}deg)` }
|
|
152
|
+
])
|
|
153
|
+
|
|
154
|
+
const triangleStyles = ref([
|
|
155
|
+
{ transform: `translate(${randomRange(-10, 10)}px, ${randomRange(-10, 10)}px) rotate(${randomRange(-3, 3)}deg)` },
|
|
156
|
+
{ transform: `translate(${randomRange(-12, 12)}px, ${randomRange(-12, 12)}px) rotate(${randomRange(-4, 4)}deg)` }
|
|
157
|
+
])
|
|
158
|
+
|
|
159
|
+
const linesStyle = ref({
|
|
160
|
+
transform: `translate(${randomRange(-15, 15)}px, ${randomRange(-15, 15)}px) rotate(${randomRange(55, 65)}deg)`
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const lineWidths = ref([
|
|
164
|
+
randomRange(180, 204),
|
|
165
|
+
randomRange(130, 158),
|
|
166
|
+
randomRange(180, 204),
|
|
167
|
+
randomRange(85, 107)
|
|
168
|
+
])
|
|
169
|
+
|
|
170
|
+
const gridStyle = ref({})
|
|
171
|
+
|
|
172
|
+
const dots = ref([
|
|
173
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
174
|
+
{ filled: false, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
175
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
176
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
177
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
178
|
+
{ filled: false, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
179
|
+
{ filled: false, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
180
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } },
|
|
181
|
+
{ filled: true, style: { transform: `scale(${randomRange(0.85, 1.15)})` } }
|
|
182
|
+
])
|
|
183
|
+
|
|
184
|
+
// アニメーション更新関数
|
|
185
|
+
const updateAnimations = () => {
|
|
186
|
+
// 円形要素をランダムに動かす
|
|
187
|
+
circleStyles.value[0] = {
|
|
188
|
+
transform: `translate(${randomRange(-15, 15)}px, ${randomRange(-15, 15)}px) rotate(${randomRange(-5, 5)}deg)`
|
|
189
|
+
}
|
|
190
|
+
circleStyles.value[1] = {
|
|
191
|
+
transform: `translate(${randomRange(-20, 20)}px, ${randomRange(-20, 20)}px) rotate(${randomRange(-8, 8)}deg)`
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 三角形要素をランダムに動かす
|
|
195
|
+
triangleStyles.value[0] = {
|
|
196
|
+
transform: `translate(${randomRange(-10, 10)}px, ${randomRange(-10, 10)}px) rotate(${randomRange(-3, 3)}deg)`
|
|
197
|
+
}
|
|
198
|
+
triangleStyles.value[1] = {
|
|
199
|
+
transform: `translate(${randomRange(-12, 12)}px, ${randomRange(-12, 12)}px) rotate(${randomRange(-4, 4)}deg)`
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 斜線要素をランダムに動かす
|
|
203
|
+
linesStyle.value = {
|
|
204
|
+
transform: `translate(${randomRange(-15, 15)}px, ${randomRange(-15, 15)}px) rotate(${randomRange(55, 65)}deg)`
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 斜線の幅をランダムに変更
|
|
208
|
+
lineWidths.value = [
|
|
209
|
+
randomRange(180, 204),
|
|
210
|
+
randomRange(130, 158),
|
|
211
|
+
randomRange(180, 204),
|
|
212
|
+
randomRange(85, 107)
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
// ドットをランダムにスケール変更
|
|
216
|
+
dots.value = dots.value.map(dot => ({
|
|
217
|
+
...dot,
|
|
218
|
+
style: {
|
|
219
|
+
transform: `scale(${randomRange(0.85, 1.15)})`
|
|
220
|
+
}
|
|
221
|
+
}))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let intervalId = null
|
|
225
|
+
|
|
226
|
+
onMounted(() => {
|
|
227
|
+
// 即座に最初のアニメーションを開始
|
|
228
|
+
setTimeout(() => {
|
|
229
|
+
updateAnimations()
|
|
230
|
+
}, 100)
|
|
231
|
+
|
|
232
|
+
// 定期的にアニメーションを更新(3秒ごと)
|
|
233
|
+
intervalId = setInterval(() => {
|
|
234
|
+
updateAnimations()
|
|
235
|
+
}, 3000)
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
onUnmounted(() => {
|
|
239
|
+
if (intervalId) {
|
|
240
|
+
clearInterval(intervalId)
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
</script>
|
|
244
|
+
|
|
245
|
+
<style scoped>
|
|
246
|
+
/* グラデーション背景のアニメーション */
|
|
247
|
+
@keyframes gradient-shift {
|
|
248
|
+
0% {
|
|
249
|
+
background: linear-gradient(to bottom right, white, #f3f4f6, #e0f2fe);
|
|
250
|
+
}
|
|
251
|
+
33% {
|
|
252
|
+
background: linear-gradient(to bottom right, white, #eff6ff, #dbeafe);
|
|
253
|
+
}
|
|
254
|
+
66% {
|
|
255
|
+
background: linear-gradient(to bottom right, white, #f3f4f6, #dbeafe);
|
|
256
|
+
}
|
|
257
|
+
100% {
|
|
258
|
+
background: linear-gradient(to bottom right, white, #f3f4f6, #e0f2fe);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.animated-gradient {
|
|
263
|
+
animation: gradient-shift 20s ease-in-out infinite;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* グリッドの常時回転アニメーション */
|
|
267
|
+
@keyframes rotate-continuously {
|
|
268
|
+
from {
|
|
269
|
+
transform: rotate(0deg);
|
|
270
|
+
}
|
|
271
|
+
to {
|
|
272
|
+
transform: rotate(360deg);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.rotating-grid {
|
|
277
|
+
animation: rotate-continuously 120s linear infinite;
|
|
278
|
+
}
|
|
279
|
+
</style>
|
package/package.json
CHANGED