slidev-theme-gtlabo 1.0.0
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/LICENSE +21 -0
- package/README.md +298 -0
- package/components/Citation.vue +253 -0
- package/components/CitationListPage.vue +249 -0
- package/components/Header.vue +354 -0
- package/components/MathText.vue +557 -0
- package/components/SectionDivider.vue +24 -0
- package/components/SectionTitle.vue +70 -0
- package/components/SubSectionTitle.vue +67 -0
- package/components/TableOfContents.vue +349 -0
- package/components/TextColorBox.vue +97 -0
- package/layouts/cover.vue +69 -0
- package/layouts/default.vue +12 -0
- package/layouts/intro.vue +7 -0
- package/package.json +65 -0
- package/setup/shiki.ts +11 -0
- package/styles/index.ts +3 -0
- package/styles/layout.css +24 -0
- package/uno.config.ts +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 mksmkss
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Slidev Theme GTlabo
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@mksmkss/slidev-theme-gtlabo)
|
|
4
|
+
|
|
5
|
+
学術発表やプレゼンテーション用に設計されたSlidev用カスタムテーマ。引用管理、数式表示、階層リストなどの機能を提供します。
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @mksmkss/slidev-theme-gtlabo
|
|
11
|
+
```
|
|
12
|
+
Add the following frontmatter to your `slides.md`. Start Slidev then it will prompt you to install the theme automatically.
|
|
13
|
+
|
|
14
|
+
<pre><code>
|
|
15
|
+
---
|
|
16
|
+
theme: <b>gtlabo</b>
|
|
17
|
+
---
|
|
18
|
+
</code></pre>
|
|
19
|
+
|
|
20
|
+
Learn more about [how to use a theme](https://sli.dev/guide/theme-addon#use-theme).
|
|
21
|
+
|
|
22
|
+
## Layouts
|
|
23
|
+
|
|
24
|
+
This theme provides the following layouts:
|
|
25
|
+
|
|
26
|
+
> TODO:
|
|
27
|
+
|
|
28
|
+
## Components
|
|
29
|
+
|
|
30
|
+
このテーマは以下のコンポーネントを提供します:
|
|
31
|
+
|
|
32
|
+
### 1. Citation コンポーネント
|
|
33
|
+
インライン引用と参考文献の管理を行います。
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<Citation id="reference-key" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**機能:**
|
|
40
|
+
- インライン引用番号の表示(`[1]`形式)
|
|
41
|
+
- 画面下部に現在のページの引用情報を表示
|
|
42
|
+
- 引用番号の自動管理
|
|
43
|
+
- 複数ページにわたる引用の追跡
|
|
44
|
+
|
|
45
|
+
**使用例:**
|
|
46
|
+
```markdown
|
|
47
|
+
この技術について<Citation id="smith2023" />の研究が参考になります。
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. CitationListPage コンポーネント
|
|
51
|
+
参考文献一覧ページを生成します。
|
|
52
|
+
|
|
53
|
+
```vue
|
|
54
|
+
<CitationListPage />
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**機能:**
|
|
58
|
+
- 全ての参考文献を一覧表示
|
|
59
|
+
- 学術スタイルでの引用フォーマット
|
|
60
|
+
- DOI、URL、ISSN等の情報表示
|
|
61
|
+
- ソート機能(キー、著者、年別)
|
|
62
|
+
|
|
63
|
+
**プロパティ:**
|
|
64
|
+
- `style`: 引用スタイル(`academic`、`ieee`、`apa`)
|
|
65
|
+
- `sortBy`: ソート基準(`key`、`author`、`year`)
|
|
66
|
+
|
|
67
|
+
### 3. Header コンポーネント
|
|
68
|
+
プレゼンテーションのヘッダー部分を管理します。
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<Header
|
|
72
|
+
:chapter-data="{ title: 'セクションタイトル' }"
|
|
73
|
+
chapter="section1"
|
|
74
|
+
current-section="intro"
|
|
75
|
+
/>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**機能:**
|
|
79
|
+
- 章・セクションの進捗表示
|
|
80
|
+
- 現在位置の可視化
|
|
81
|
+
- ページ番号表示
|
|
82
|
+
- 動的なプログレスバー
|
|
83
|
+
|
|
84
|
+
**プロパティ:**
|
|
85
|
+
- `chapter`: 章のキー
|
|
86
|
+
- `chapterData`: 章の情報オブジェクト
|
|
87
|
+
- `currentSection`: 現在のセクション
|
|
88
|
+
- `currentChapter`: 現在の章
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### 4. MathText コンポーネント
|
|
92
|
+
数式とテキストを統合表示します。
|
|
93
|
+
|
|
94
|
+
```vue
|
|
95
|
+
<MathText
|
|
96
|
+
text="これは数式 $x^2 + y^2 = z^2$ を含むテキストです。"
|
|
97
|
+
container-tag="p"
|
|
98
|
+
:simple="false"
|
|
99
|
+
:disable-markdown="false"
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**機能:**
|
|
104
|
+
- LaTeX数式の自動レンダリング
|
|
105
|
+
- インライン数式(`$...$`)とブロック数式(`$$...$$`)
|
|
106
|
+
- Markdownサポート(太字、イタリック、リンク等)
|
|
107
|
+
- KaTeX による数式描画
|
|
108
|
+
- シンプルモード対応
|
|
109
|
+
|
|
110
|
+
**プロパティ:**
|
|
111
|
+
- `text`: 表示するテキスト
|
|
112
|
+
- `containerTag`: コンテナのHTMLタグ
|
|
113
|
+
- `simple`: シンプルモード(基本的な数式のみ)
|
|
114
|
+
- `disableMarkdown`: Markdownを無効化
|
|
115
|
+
- `customDelimiters`: カスタム区切り文字
|
|
116
|
+
|
|
117
|
+
### 5. SectionTitle コンポーネント
|
|
118
|
+
セクションタイトルを表示します。
|
|
119
|
+
|
|
120
|
+
```vue
|
|
121
|
+
<SectionTitle
|
|
122
|
+
title="セクションタイトル"
|
|
123
|
+
color="sky-800"
|
|
124
|
+
/>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**機能:**
|
|
128
|
+
- 左側のカラーバーと組み合わせたタイトル表示
|
|
129
|
+
- UnoCSS/Tailwindカラー対応
|
|
130
|
+
- カスタムカラー対応
|
|
131
|
+
- スロットコンテンツ対応
|
|
132
|
+
|
|
133
|
+
**プロパティ:**
|
|
134
|
+
- `title`: タイトルテキスト
|
|
135
|
+
- `color`: カラー(Tailwind形式またはHEX)
|
|
136
|
+
|
|
137
|
+
### 6. SubSectionTitle コンポーネント
|
|
138
|
+
サブセクションタイトルを表示します。
|
|
139
|
+
|
|
140
|
+
```vue
|
|
141
|
+
<SubSectionTitle
|
|
142
|
+
title="サブセクションタイトル"
|
|
143
|
+
color="sky-700"
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**機能:**
|
|
148
|
+
- 左側のアイコン(矢印)と組み合わせたタイトル表示
|
|
149
|
+
- UnoCSS/Tailwindカラー対応
|
|
150
|
+
- カスタムカラー対応
|
|
151
|
+
|
|
152
|
+
**プロパティ:**
|
|
153
|
+
- `title`: タイトルテキスト
|
|
154
|
+
- `color`: カラー(Tailwind形式またはHEX)
|
|
155
|
+
|
|
156
|
+
### 7. TextColorBox コンポーネント
|
|
157
|
+
色付きのテキストボックスを表示します。
|
|
158
|
+
|
|
159
|
+
```vue
|
|
160
|
+
<TextColorBox
|
|
161
|
+
title="タイトル"
|
|
162
|
+
text="本文テキスト"
|
|
163
|
+
container-class="my-4"
|
|
164
|
+
/>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**機能:**
|
|
168
|
+
- タイトル付きのカラーボックス
|
|
169
|
+
- HTMLタグ対応
|
|
170
|
+
- マーキング機能(`v-mark`)
|
|
171
|
+
- カスタムスタイル適用
|
|
172
|
+
|
|
173
|
+
**プロパティ:**
|
|
174
|
+
- `title`: ボックスのタイトル
|
|
175
|
+
- `text`: ボックスの本文
|
|
176
|
+
- `containerClass`: 追加のCSSクラス
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
**機能:**
|
|
180
|
+
- SVGベースの入れ子円グラフ
|
|
181
|
+
- データ構造の階層表示
|
|
182
|
+
- アニメーション効果
|
|
183
|
+
- 課題提起セクション付き
|
|
184
|
+
- パーセンテージ表示
|
|
185
|
+
|
|
186
|
+
**特徴:**
|
|
187
|
+
- 外側の円:全体データの分類(構造化/非構造化)
|
|
188
|
+
- 内側の円:構造化データの詳細分類
|
|
189
|
+
- 自動アニメーション効果
|
|
190
|
+
- 完全にカスタマイズ可能なSVG
|
|
191
|
+
|
|
192
|
+
## 🛠️ 設定方法
|
|
193
|
+
|
|
194
|
+
### 1. 参考文献の設定
|
|
195
|
+
|
|
196
|
+
frontmatter に `citations` を追加:
|
|
197
|
+
|
|
198
|
+
```yaml
|
|
199
|
+
---
|
|
200
|
+
citations:
|
|
201
|
+
smith2023:
|
|
202
|
+
author: "Smith, J."
|
|
203
|
+
title: "Research on AI"
|
|
204
|
+
journal: "Journal of AI"
|
|
205
|
+
year: "2023"
|
|
206
|
+
doi: "10.1000/example"
|
|
207
|
+
jones2022:
|
|
208
|
+
author: "Jones, A."
|
|
209
|
+
title: "Machine Learning Basics"
|
|
210
|
+
publisher: "Tech Press"
|
|
211
|
+
year: "2022"
|
|
212
|
+
---
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### 2. 章・セクション構造の設定
|
|
216
|
+
|
|
217
|
+
```yaml
|
|
218
|
+
---
|
|
219
|
+
chapters:
|
|
220
|
+
intro:
|
|
221
|
+
title: "はじめに"
|
|
222
|
+
sections:
|
|
223
|
+
overview:
|
|
224
|
+
title: "概要"
|
|
225
|
+
objectives:
|
|
226
|
+
title: "目的"
|
|
227
|
+
method:
|
|
228
|
+
title: "手法"
|
|
229
|
+
sections:
|
|
230
|
+
approach:
|
|
231
|
+
title: "アプローチ"
|
|
232
|
+
implementation:
|
|
233
|
+
title: "実装"
|
|
234
|
+
---
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 📱 使用例
|
|
238
|
+
|
|
239
|
+
```vue
|
|
240
|
+
<template>
|
|
241
|
+
<div>
|
|
242
|
+
<!-- ヘッダー -->
|
|
243
|
+
<Header
|
|
244
|
+
:chapter-data="{ title: '研究手法' }"
|
|
245
|
+
chapter="method"
|
|
246
|
+
current-section="approach"
|
|
247
|
+
/>
|
|
248
|
+
|
|
249
|
+
<!-- セクションタイトル -->
|
|
250
|
+
<SectionTitle title="提案手法" />
|
|
251
|
+
|
|
252
|
+
<!-- 数式を含むテキスト -->
|
|
253
|
+
<MathText
|
|
254
|
+
text="提案手法では、損失関数 $L = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y_i})^2$ を最小化します。"
|
|
255
|
+
/>
|
|
256
|
+
|
|
257
|
+
<!-- 階層リスト -->
|
|
258
|
+
<HierarchyList>
|
|
259
|
+
- 手法の特徴
|
|
260
|
+
- 高精度
|
|
261
|
+
- 高速処理
|
|
262
|
+
- 省メモリ
|
|
263
|
+
</HierarchyList>
|
|
264
|
+
|
|
265
|
+
<!-- 引用 -->
|
|
266
|
+
<p>この手法は<Citation id="smith2023" />で提案されました。</p>
|
|
267
|
+
|
|
268
|
+
<!-- カラーボックス -->
|
|
269
|
+
<TextColorBox
|
|
270
|
+
title="重要なポイント"
|
|
271
|
+
text="この手法により従来手法より<strong>20%</strong>の性能向上を実現しました。"
|
|
272
|
+
/>
|
|
273
|
+
</div>
|
|
274
|
+
</template>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 🎨 スタイル
|
|
278
|
+
|
|
279
|
+
テーマは以下のカラーパレットを使用:
|
|
280
|
+
- プライマリ: Sky(`sky-600`、`sky-700`、`sky-800`)
|
|
281
|
+
- セカンダリ: Gray(`gray-600`、`gray-700`、`gray-800`)
|
|
282
|
+
- アクセント: Blue(`blue-500`、`blue-600`)
|
|
283
|
+
|
|
284
|
+
## 📦 依存関係
|
|
285
|
+
|
|
286
|
+
- Vue 3
|
|
287
|
+
- Slidev
|
|
288
|
+
- UnoCSS/Tailwind CSS
|
|
289
|
+
- KaTeX(数式レンダリング)
|
|
290
|
+
- Lucide Icons
|
|
291
|
+
|
|
292
|
+
## Contributing
|
|
293
|
+
|
|
294
|
+
- `npm install`
|
|
295
|
+
- `npm run dev` to start theme preview of `example.md`
|
|
296
|
+
- Edit the `example.md` and style to see the changes
|
|
297
|
+
- `npm run export` to generate the preview PDF
|
|
298
|
+
- `npm run screenshot` to generate the preview PNG
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span>
|
|
3
|
+
<!-- インライン引用番号 -->
|
|
4
|
+
<sup class="text-blue-600 font-semibold">
|
|
5
|
+
[{{ citationNumber }}]
|
|
6
|
+
</sup>
|
|
7
|
+
|
|
8
|
+
<!-- 引用情報表示エリア(画面下部に常時表示) -->
|
|
9
|
+
<div
|
|
10
|
+
v-if="hasCurrentPageCitations"
|
|
11
|
+
class="fixed bottom-0 left-0 right-0 bg-white border-t-2 border-gray-300 shadow-lg z-40 max-h-32 overflow-y-auto"
|
|
12
|
+
style="pointer-events: none;"
|
|
13
|
+
>
|
|
14
|
+
<div class="max-w-7xl mx-auto px-4 py-2">
|
|
15
|
+
<div class="space-y-1">
|
|
16
|
+
<div
|
|
17
|
+
v-for="citation in sortedCurrentPageCitations"
|
|
18
|
+
:key="citation.id"
|
|
19
|
+
class="text-xs text-gray-800"
|
|
20
|
+
>
|
|
21
|
+
<span class="font-semibold">[{{ citation.number }}]</span>
|
|
22
|
+
{{ citation.formatted }}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</span>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
32
|
+
import { useSlideContext } from '@slidev/client'
|
|
33
|
+
|
|
34
|
+
const { $slidev } = useSlideContext()
|
|
35
|
+
const citations = $slidev.configs.citations || {}
|
|
36
|
+
|
|
37
|
+
const props = defineProps({
|
|
38
|
+
id: {
|
|
39
|
+
type: String,
|
|
40
|
+
required: true
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// グローバル引用管理の初期化
|
|
45
|
+
if (!window.citationManager) {
|
|
46
|
+
window.citationManager = {
|
|
47
|
+
counter: 1,
|
|
48
|
+
citations: new Map(), // id -> { number, data, formatted }
|
|
49
|
+
pageActiveCitations: new Map(), // pageNumber -> Set(citationIds)
|
|
50
|
+
components: new Set()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const forceUpdate = ref(0)
|
|
55
|
+
|
|
56
|
+
// 現在のページ番号を取得
|
|
57
|
+
const currentPage = computed(() => {
|
|
58
|
+
return $slidev.nav.currentPage
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// 引用データを取得
|
|
62
|
+
const citationData = computed(() => {
|
|
63
|
+
return citations[props.id] || null
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// 引用番号を取得または生成
|
|
67
|
+
const citationNumber = computed(() => {
|
|
68
|
+
if (!citationData.value) return '?'
|
|
69
|
+
|
|
70
|
+
if (!window.citationManager.citations.has(props.id)) {
|
|
71
|
+
window.citationManager.citations.set(props.id, {
|
|
72
|
+
number: window.citationManager.counter,
|
|
73
|
+
data: citationData.value,
|
|
74
|
+
formatted: formatCitation(citationData.value)
|
|
75
|
+
})
|
|
76
|
+
window.citationManager.counter++
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return window.citationManager.citations.get(props.id).number
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// 現在のページにアクティブな引用があるかチェック
|
|
83
|
+
const hasCurrentPageCitations = computed(() => {
|
|
84
|
+
forceUpdate.value // 依存関係を強制的に更新
|
|
85
|
+
const pageSet = window.citationManager.pageActiveCitations.get(currentPage.value)
|
|
86
|
+
return pageSet && pageSet.size > 0
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// 現在のページのソートされた引用一覧
|
|
90
|
+
const sortedCurrentPageCitations = computed(() => {
|
|
91
|
+
forceUpdate.value // 依存関係を強制的に更新
|
|
92
|
+
const pageSet = window.citationManager.pageActiveCitations.get(currentPage.value)
|
|
93
|
+
|
|
94
|
+
if (!pageSet) return []
|
|
95
|
+
|
|
96
|
+
return Array.from(pageSet)
|
|
97
|
+
.map(id => ({
|
|
98
|
+
id,
|
|
99
|
+
...window.citationManager.citations.get(id)
|
|
100
|
+
}))
|
|
101
|
+
.filter(citation => citation.data) // dataが存在するもののみ
|
|
102
|
+
.sort((a, b) => a.number - b.number)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// 引用をフォーマット
|
|
106
|
+
const formatCitation = (data) => {
|
|
107
|
+
if (!data) return '引用情報が見つかりません'
|
|
108
|
+
|
|
109
|
+
let citation = ''
|
|
110
|
+
|
|
111
|
+
// 著者
|
|
112
|
+
if (data.author) {
|
|
113
|
+
citation += data.author
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// タイトル
|
|
117
|
+
if (data.title) {
|
|
118
|
+
citation += citation ? `, "${data.title}"` : `"${data.title}"`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ジャーナル
|
|
122
|
+
if (data.journal) {
|
|
123
|
+
citation += citation ? `, ${data.journal}` : data.journal
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ボリューム・ナンバー
|
|
127
|
+
if (data.volume && data.number) {
|
|
128
|
+
citation += `, Vol. ${data.volume}, No. ${data.number}`
|
|
129
|
+
} else if (data.volume) {
|
|
130
|
+
citation += `, Vol. ${data.volume}`
|
|
131
|
+
} else if (data.number) {
|
|
132
|
+
citation += `, No. ${data.number}`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ページ
|
|
136
|
+
if (data.pages) {
|
|
137
|
+
citation += `, pp. ${data.pages}`
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 年
|
|
141
|
+
if (data.year) {
|
|
142
|
+
citation += citation ? ` (${data.year})` : data.year
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 出版社
|
|
146
|
+
if (data.publisher) {
|
|
147
|
+
citation += citation ? `, ${data.publisher}` : data.publisher
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// URL
|
|
151
|
+
if (data.url) {
|
|
152
|
+
citation += citation ? `, ${data.url}` : data.url
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ISSN
|
|
156
|
+
if (data.issn) {
|
|
157
|
+
citation += `, ISSN: ${data.issn}`
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return citation || '引用情報が不完全です'
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 全コンポーネントの再描画をトリガー
|
|
164
|
+
const triggerGlobalUpdate = () => {
|
|
165
|
+
window.citationManager.components.forEach(component => {
|
|
166
|
+
if (component.updateForceUpdate) {
|
|
167
|
+
component.updateForceUpdate()
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 強制更新関数
|
|
173
|
+
const updateForceUpdate = () => {
|
|
174
|
+
forceUpdate.value++
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 現在のページに引用を追加
|
|
178
|
+
const addToCurrentPage = () => {
|
|
179
|
+
if (!citationData.value) return
|
|
180
|
+
|
|
181
|
+
const page = currentPage.value
|
|
182
|
+
if (!window.citationManager.pageActiveCitations.has(page)) {
|
|
183
|
+
window.citationManager.pageActiveCitations.set(page, new Set())
|
|
184
|
+
}
|
|
185
|
+
window.citationManager.pageActiveCitations.get(page).add(props.id)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 現在のページから引用を削除
|
|
189
|
+
const removeFromCurrentPage = () => {
|
|
190
|
+
const page = currentPage.value
|
|
191
|
+
const pageSet = window.citationManager.pageActiveCitations.get(page)
|
|
192
|
+
if (pageSet) {
|
|
193
|
+
pageSet.delete(props.id)
|
|
194
|
+
if (pageSet.size === 0) {
|
|
195
|
+
window.citationManager.pageActiveCitations.delete(page)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ページ変更を監視
|
|
201
|
+
watch(currentPage, (newPage, oldPage) => {
|
|
202
|
+
if (oldPage !== undefined) {
|
|
203
|
+
// 前のページから削除
|
|
204
|
+
const oldPageSet = window.citationManager.pageActiveCitations.get(oldPage)
|
|
205
|
+
if (oldPageSet) {
|
|
206
|
+
oldPageSet.delete(props.id)
|
|
207
|
+
if (oldPageSet.size === 0) {
|
|
208
|
+
window.citationManager.pageActiveCitations.delete(oldPage)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 新しいページに追加
|
|
214
|
+
addToCurrentPage()
|
|
215
|
+
triggerGlobalUpdate()
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
// コンポーネントのマウント時
|
|
219
|
+
onMounted(() => {
|
|
220
|
+
if (citationData.value) {
|
|
221
|
+
addToCurrentPage()
|
|
222
|
+
window.citationManager.components.add({ updateForceUpdate })
|
|
223
|
+
triggerGlobalUpdate()
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
// コンポーネントのアンマウント時
|
|
228
|
+
onUnmounted(() => {
|
|
229
|
+
removeFromCurrentPage()
|
|
230
|
+
window.citationManager.components.delete({ updateForceUpdate })
|
|
231
|
+
triggerGlobalUpdate()
|
|
232
|
+
})
|
|
233
|
+
</script>
|
|
234
|
+
|
|
235
|
+
<style scoped>
|
|
236
|
+
/* スクロールバーのスタイリング */
|
|
237
|
+
::-webkit-scrollbar {
|
|
238
|
+
width: 4px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
::-webkit-scrollbar-track {
|
|
242
|
+
background: #f1f1f1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
::-webkit-scrollbar-thumb {
|
|
246
|
+
background: #c1c1c1;
|
|
247
|
+
border-radius: 2px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
::-webkit-scrollbar-thumb:hover {
|
|
251
|
+
background: #a8a8a8;
|
|
252
|
+
}
|
|
253
|
+
</style>
|