vimd 0.5.6 → 0.5.8

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.
@@ -0,0 +1,135 @@
1
+ -- filters/latex-metadata.lua
2
+ -- Extract metadata from AGU journal format LaTeX and insert as HTML at document start
3
+
4
+ local extracted = {
5
+ title = nil,
6
+ authors = nil,
7
+ affiliations = {},
8
+ corresponding = nil,
9
+ keypoints = {},
10
+ abstract = nil
11
+ }
12
+
13
+ -- Convert \affil{n} to <sup>n</sup>
14
+ local function process_affil(text)
15
+ return text:gsub('\\affil{(%d+)}', '<sup>%1</sup>')
16
+ end
17
+
18
+ -- Extract title and abstract from Meta (pandoc processes these as metadata)
19
+ function Meta(meta)
20
+ if meta.title then
21
+ extracted.title = pandoc.utils.stringify(meta.title)
22
+ end
23
+ if meta.abstract then
24
+ extracted.abstract = pandoc.utils.stringify(meta.abstract)
25
+ end
26
+ return meta
27
+ end
28
+
29
+ function RawBlock(el)
30
+ if el.format:match('latex') or el.format:match('tex') then
31
+ local text = el.text
32
+
33
+ -- Extract \authors{...}
34
+ local authors = text:match('\\authors%s*{(.+)}')
35
+ if authors then
36
+ extracted.authors = process_affil(authors)
37
+ end
38
+
39
+ -- Extract \affiliation{n}{...}
40
+ local affil_num, affil_text = text:match('\\affiliation%s*{(%d+)}%s*{(.+)}')
41
+ if affil_num and affil_text then
42
+ extracted.affiliations[tonumber(affil_num)] = affil_text
43
+ end
44
+
45
+ -- Extract \correspondingauthor{name}{email}
46
+ local corr_name, corr_email = text:match('\\correspondingauthor%s*{([^}]+)}%s*{([^}]+)}')
47
+ if corr_name and corr_email then
48
+ extracted.corresponding = { name = corr_name, email = corr_email }
49
+ end
50
+
51
+ -- Extract \begin{keypoints}...\end{keypoints}
52
+ local keypoints_content = text:match('\\begin{keypoints}(.-)\\end{keypoints}')
53
+ if keypoints_content then
54
+ -- Extract each \item content
55
+ for item in keypoints_content:gmatch('\\item%s*([^\n]+)') do
56
+ -- Trim whitespace
57
+ item = item:gsub('^%s*', ''):gsub('%s*$', '')
58
+ if item ~= '' then
59
+ table.insert(extracted.keypoints, item)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ return el
65
+ end
66
+
67
+ function Pandoc(doc)
68
+ local header_blocks = {}
69
+
70
+ -- 1. Title
71
+ if extracted.title then
72
+ table.insert(header_blocks, pandoc.RawBlock('html',
73
+ '<h1 class="vimd-title">' .. extracted.title .. '</h1>'))
74
+ end
75
+
76
+ -- 2. Authors
77
+ if extracted.authors then
78
+ table.insert(header_blocks, pandoc.RawBlock('html',
79
+ '<div class="vimd-authors">' .. extracted.authors .. '</div>'))
80
+ end
81
+
82
+ -- 3. Affiliations
83
+ if next(extracted.affiliations) then
84
+ local affil_html = '<div class="vimd-affiliations">'
85
+ -- Sort by affiliation number
86
+ local sorted_keys = {}
87
+ for k in pairs(extracted.affiliations) do
88
+ table.insert(sorted_keys, k)
89
+ end
90
+ table.sort(sorted_keys)
91
+ for _, i in ipairs(sorted_keys) do
92
+ local affil = extracted.affiliations[i]
93
+ affil_html = affil_html .. '<div class="vimd-affiliation"><sup>' .. i .. '</sup> ' .. affil .. '</div>'
94
+ end
95
+ affil_html = affil_html .. '</div>'
96
+ table.insert(header_blocks, pandoc.RawBlock('html', affil_html))
97
+ end
98
+
99
+ -- 4. Corresponding author
100
+ if extracted.corresponding then
101
+ local corr_html = '<div class="vimd-corresponding">Corresponding author: '
102
+ .. extracted.corresponding.name .. ' (<a href="mailto:' .. extracted.corresponding.email .. '">'
103
+ .. extracted.corresponding.email .. '</a>)</div>'
104
+ table.insert(header_blocks, pandoc.RawBlock('html', corr_html))
105
+ end
106
+
107
+ -- 5. Key Points
108
+ if #extracted.keypoints > 0 then
109
+ local kp_html = '<div class="vimd-keypoints"><h2>Key Points</h2><ul>'
110
+ for _, item in ipairs(extracted.keypoints) do
111
+ kp_html = kp_html .. '<li>' .. item .. '</li>'
112
+ end
113
+ kp_html = kp_html .. '</ul></div>'
114
+ table.insert(header_blocks, pandoc.RawBlock('html', kp_html))
115
+ end
116
+
117
+ -- 6. Abstract
118
+ if extracted.abstract then
119
+ table.insert(header_blocks, pandoc.RawBlock('html',
120
+ '<div class="vimd-abstract"><h2>Abstract</h2><p>' .. extracted.abstract .. '</p></div>'))
121
+ end
122
+
123
+ -- Insert at document start (in reverse order to maintain order)
124
+ for i = #header_blocks, 1, -1 do
125
+ table.insert(doc.blocks, 1, header_blocks[i])
126
+ end
127
+
128
+ return doc
129
+ end
130
+
131
+ return {
132
+ { Meta = Meta },
133
+ { RawBlock = RawBlock },
134
+ { Pandoc = Pandoc }
135
+ }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ export type { VimdConfig, ThemeInfo } from './config/types.js';
2
2
  export { defineConfig } from './config/types.js';
3
3
  export { MarkdownConverter } from './core/converter.js';
4
4
  export { FileWatcher } from './core/watcher.js';
5
- export { WebSocketServer } from './core/websocket-server.js';
6
5
  export { PandocDetector } from './core/pandoc-detector.js';
7
6
  export { ThemeManager } from './themes/index.js';
8
7
  export { ConfigLoader } from './config/loader.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ export { defineConfig } from './config/types.js';
4
4
  // ==================== コア機能エクスポート ====================
5
5
  export { MarkdownConverter } from './core/converter.js';
6
6
  export { FileWatcher } from './core/watcher.js';
7
- export { WebSocketServer } from './core/websocket-server.js';
8
7
  export { PandocDetector } from './core/pandoc-detector.js';
9
8
  // ==================== テーマ管理エクスポート ====================
10
9
  export { ThemeManager } from './themes/index.js';
@@ -29,11 +29,15 @@
29
29
  </style>
30
30
  <script>
31
31
  MathJax = {
32
- loader: {load: ['[tex]/bussproofs', '[tex]/ams', '[tex]/physics']},
32
+ loader: {load: ['[tex]/bussproofs', '[tex]/ams', '[tex]/physics', '[tex]/boldsymbol']},
33
33
  tex: {
34
- packages: {'[+]': ['bussproofs', 'ams', 'physics']},
34
+ packages: {'[+]': ['bussproofs', 'ams', 'physics', 'boldsymbol']},
35
35
  inlineMath: [['$', '$'], ['\\(', '\\)']],
36
- displayMath: [['$$', '$$'], ['\\[', '\\]']]
36
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
37
+ tags: 'ams',
38
+ macros: {
39
+ bm: ['\\boldsymbol{#1}', 1]
40
+ }
37
41
  }
38
42
  };
39
43
  </script>
@@ -27,11 +27,15 @@
27
27
  </style>
28
28
  <script>
29
29
  MathJax = {
30
- loader: {load: ['[tex]/bussproofs', '[tex]/ams', '[tex]/physics']},
30
+ loader: {load: ['[tex]/bussproofs', '[tex]/ams', '[tex]/physics', '[tex]/boldsymbol']},
31
31
  tex: {
32
- packages: {'[+]': ['bussproofs', 'ams', 'physics']},
32
+ packages: {'[+]': ['bussproofs', 'ams', 'physics', 'boldsymbol']},
33
33
  inlineMath: [['$', '$'], ['\\(', '\\)']],
34
- displayMath: [['$$', '$$'], ['\\[', '\\]']]
34
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
35
+ tags: 'ams',
36
+ macros: {
37
+ bm: ['\\boldsymbol{#1}', 1]
38
+ }
35
39
  }
36
40
  };
37
41
  </script>
@@ -0,0 +1,259 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="generator" content="vimd">
7
+ <title>{{title}} - vimd</title>
8
+ <style>
9
+ {{theme_css}}
10
+ </style>
11
+ <style>
12
+ /* Single file mode styles */
13
+ * {
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ html, body {
18
+ margin: 0;
19
+ padding: 0;
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+
24
+ body {
25
+ overflow: hidden;
26
+ }
27
+
28
+ .vimd-single-container {
29
+ width: 100%;
30
+ height: 100vh;
31
+ overflow-y: auto;
32
+ overflow-x: hidden;
33
+ }
34
+
35
+ .vimd-single-content {
36
+ padding: 32px;
37
+ max-width: 720px;
38
+ margin: 0 auto;
39
+ }
40
+
41
+ .vimd-single-content pre,
42
+ .vimd-single-content table {
43
+ overflow-x: auto;
44
+ }
45
+
46
+ /* Connection status indicator */
47
+ .vimd-connection-status {
48
+ position: fixed;
49
+ bottom: 16px;
50
+ right: 16px;
51
+ padding: 8px 12px;
52
+ background: rgba(0, 0, 0, 0.7);
53
+ color: #fff;
54
+ font-size: 12px;
55
+ border-radius: 4px;
56
+ opacity: 0;
57
+ transition: opacity 0.3s;
58
+ pointer-events: none;
59
+ z-index: 1000;
60
+ }
61
+
62
+ .vimd-connection-status.visible {
63
+ opacity: 1;
64
+ }
65
+
66
+ .vimd-connection-status.error {
67
+ background: rgba(211, 47, 47, 0.9);
68
+ }
69
+ </style>
70
+ {{#if math_enabled}}
71
+ <style>
72
+ /* Block math centering */
73
+ .math-block {
74
+ display: block;
75
+ text-align: center;
76
+ margin: 1em 0;
77
+ }
78
+ mjx-container[display="true"] {
79
+ display: block !important;
80
+ text-align: center !important;
81
+ margin: 1em 0 !important;
82
+ }
83
+ </style>
84
+ <script>
85
+ MathJax = {
86
+ loader: {load: ['[tex]/bussproofs', '[tex]/ams', '[tex]/physics', '[tex]/boldsymbol']},
87
+ tex: {
88
+ packages: {'[+]': ['bussproofs', 'ams', 'physics', 'boldsymbol']},
89
+ inlineMath: [['$', '$'], ['\\(', '\\)']],
90
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
91
+ tags: 'ams',
92
+ macros: {
93
+ bm: ['\\boldsymbol{#1}', 1]
94
+ }
95
+ }
96
+ };
97
+ </script>
98
+ <script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
99
+ {{/if}}
100
+ </head>
101
+ <body>
102
+ <div class="vimd-single-container" id="container">
103
+ <article class="vimd-single-content markdown-body" id="content">
104
+ <!-- Content will be loaded via WebSocket -->
105
+ </article>
106
+ </div>
107
+
108
+ <div class="vimd-connection-status" id="status"></div>
109
+
110
+ <script>
111
+ (function() {
112
+ 'use strict';
113
+
114
+ var container = document.getElementById('container');
115
+ var content = document.getElementById('content');
116
+ var status = document.getElementById('status');
117
+ var ws = null;
118
+ var reconnectAttempts = 0;
119
+ var maxReconnectAttempts = 10;
120
+ var reconnectDelay = 1000;
121
+
122
+ /**
123
+ * Show connection status message
124
+ */
125
+ function showStatus(message, isError) {
126
+ status.textContent = message;
127
+ status.classList.toggle('error', isError);
128
+ status.classList.add('visible');
129
+
130
+ // Hide after 3 seconds for non-error messages
131
+ if (!isError) {
132
+ setTimeout(function() {
133
+ status.classList.remove('visible');
134
+ }, 3000);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Hide connection status
140
+ */
141
+ function hideStatus() {
142
+ status.classList.remove('visible');
143
+ }
144
+
145
+ /**
146
+ * Connect to WebSocket server
147
+ */
148
+ function connect() {
149
+ var protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
150
+ ws = new WebSocket(protocol + '//' + location.host);
151
+
152
+ ws.onopen = function() {
153
+ console.log('[vimd] WebSocket connected');
154
+ reconnectAttempts = 0;
155
+ hideStatus();
156
+ };
157
+
158
+ ws.onmessage = function(event) {
159
+ try {
160
+ var msg = JSON.parse(event.data);
161
+ handleMessage(msg);
162
+ } catch (e) {
163
+ console.error('[vimd] Failed to parse message:', e);
164
+ }
165
+ };
166
+
167
+ ws.onclose = function() {
168
+ console.log('[vimd] WebSocket disconnected');
169
+
170
+ if (reconnectAttempts < maxReconnectAttempts) {
171
+ reconnectAttempts++;
172
+ showStatus('Reconnecting... (' + reconnectAttempts + '/' + maxReconnectAttempts + ')', false);
173
+ setTimeout(connect, reconnectDelay);
174
+ } else {
175
+ showStatus('Connection lost. Please refresh the page.', true);
176
+ }
177
+ };
178
+
179
+ ws.onerror = function(error) {
180
+ console.error('[vimd] WebSocket error:', error);
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Handle incoming WebSocket message
186
+ */
187
+ function handleMessage(msg) {
188
+ switch (msg.type) {
189
+ case 'content':
190
+ updateContent(msg.data.html);
191
+ if (msg.data.title) {
192
+ document.title = msg.data.title + ' - vimd';
193
+ }
194
+ break;
195
+
196
+ case 'error':
197
+ showError(msg.data.message);
198
+ break;
199
+
200
+ default:
201
+ console.warn('[vimd] Unknown message type:', msg.type);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Update content with scroll position preservation
207
+ */
208
+ function updateContent(html) {
209
+ // Save scroll position
210
+ var scrollTop = container.scrollTop;
211
+
212
+ // Update content
213
+ content.innerHTML = html;
214
+
215
+ // Re-render MathJax if available
216
+ if (window.MathJax && window.MathJax.typeset) {
217
+ // MathJax.typeset returns a promise in v3
218
+ var promise = window.MathJax.typeset([content]);
219
+
220
+ // Restore scroll position after MathJax completes
221
+ if (promise && promise.then) {
222
+ promise.then(function() {
223
+ container.scrollTop = scrollTop;
224
+ }).catch(function() {
225
+ // Restore scroll even if MathJax fails
226
+ container.scrollTop = scrollTop;
227
+ });
228
+ } else {
229
+ // Fallback: restore scroll immediately
230
+ container.scrollTop = scrollTop;
231
+ }
232
+ } else {
233
+ // No MathJax: restore scroll immediately
234
+ container.scrollTop = scrollTop;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Show error message
240
+ */
241
+ function showError(message) {
242
+ content.innerHTML = '<div class="vimd-error"><h2>Error</h2><p>' + escapeHtml(message) + '</p></div>';
243
+ }
244
+
245
+ /**
246
+ * Escape HTML special characters
247
+ */
248
+ function escapeHtml(text) {
249
+ var div = document.createElement('div');
250
+ div.textContent = text;
251
+ return div.innerHTML;
252
+ }
253
+
254
+ // Initialize connection
255
+ connect();
256
+ })();
257
+ </script>
258
+ </body>
259
+ </html>
@@ -643,6 +643,105 @@ body mark {
643
643
  }
644
644
  }
645
645
 
646
+ /* ============================================
647
+ LaTeX Metadata
648
+ ============================================ */
649
+ .vimd-authors {
650
+ font-size: 1.1em;
651
+ margin-bottom: 0.5em;
652
+ color: #2c3e50;
653
+ text-align: center;
654
+ }
655
+
656
+ .vimd-authors sup {
657
+ color: #c0392b;
658
+ font-weight: bold;
659
+ }
660
+
661
+ .vimd-affiliations {
662
+ font-size: 0.9em;
663
+ color: #7f8c8d;
664
+ margin-bottom: 0.5em;
665
+ text-align: center;
666
+ }
667
+
668
+ .vimd-affiliation {
669
+ margin-bottom: 0.25em;
670
+ }
671
+
672
+ .vimd-affiliation sup {
673
+ color: #c0392b;
674
+ font-weight: bold;
675
+ margin-right: 0.25em;
676
+ }
677
+
678
+ .vimd-corresponding {
679
+ font-size: 0.9em;
680
+ color: #7f8c8d;
681
+ font-style: italic;
682
+ margin-bottom: 1.5em;
683
+ padding-bottom: 1em;
684
+ border-bottom: 1px solid #ecf0f1;
685
+ text-align: center;
686
+ }
687
+
688
+ .vimd-corresponding a {
689
+ color: #2980b9;
690
+ }
691
+
692
+ /* LaTeX document title */
693
+ .vimd-title {
694
+ font-size: 1.8em;
695
+ font-weight: bold;
696
+ text-align: center;
697
+ margin-bottom: 0.5em;
698
+ color: #2c3e50;
699
+ }
700
+
701
+ /* Key Points box */
702
+ .vimd-keypoints {
703
+ background-color: #f8f9fa;
704
+ border: 1px solid #ecf0f1;
705
+ border-radius: 4px;
706
+ padding: 1em;
707
+ margin: 1em 0;
708
+ }
709
+
710
+ .vimd-keypoints h2 {
711
+ font-size: 1.1em;
712
+ margin-top: 0;
713
+ margin-bottom: 0.5em;
714
+ color: #2c3e50;
715
+ }
716
+
717
+ .vimd-keypoints ul {
718
+ margin: 0;
719
+ padding-left: 1.5em;
720
+ }
721
+
722
+ .vimd-keypoints li {
723
+ margin-bottom: 0.3em;
724
+ }
725
+
726
+ /* Abstract section */
727
+ .vimd-abstract {
728
+ border-left: 4px solid #2980b9;
729
+ padding-left: 1em;
730
+ margin: 1em 0;
731
+ }
732
+
733
+ .vimd-abstract h2 {
734
+ font-size: 1.1em;
735
+ margin-top: 0;
736
+ margin-bottom: 0.5em;
737
+ color: #2c3e50;
738
+ }
739
+
740
+ .vimd-abstract p {
741
+ margin: 0;
742
+ text-align: justify;
743
+ }
744
+
646
745
  /* ============================================
647
746
  Responsive
648
747
  ============================================ */
@@ -516,6 +516,100 @@ body a:focus {
516
516
  outline-offset: -2px;
517
517
  }
518
518
 
519
+ /* LaTeX metadata styles */
520
+ .vimd-authors {
521
+ font-size: 1.1em;
522
+ margin-bottom: 0.5em;
523
+ color: #e6edf3;
524
+ }
525
+
526
+ .vimd-authors sup {
527
+ color: #58a6ff;
528
+ font-weight: bold;
529
+ }
530
+
531
+ .vimd-affiliations {
532
+ font-size: 0.9em;
533
+ color: #8b949e;
534
+ margin-bottom: 0.5em;
535
+ }
536
+
537
+ .vimd-affiliation {
538
+ margin-bottom: 0.25em;
539
+ }
540
+
541
+ .vimd-affiliation sup {
542
+ color: #58a6ff;
543
+ font-weight: bold;
544
+ margin-right: 0.25em;
545
+ }
546
+
547
+ .vimd-corresponding {
548
+ font-size: 0.9em;
549
+ color: #8b949e;
550
+ font-style: italic;
551
+ margin-bottom: 1.5em;
552
+ padding-bottom: 1em;
553
+ border-bottom: 1px solid #30363d;
554
+ }
555
+
556
+ .vimd-corresponding a {
557
+ color: #58a6ff;
558
+ }
559
+
560
+ /* LaTeX document title */
561
+ .vimd-title {
562
+ font-size: 1.8em;
563
+ font-weight: bold;
564
+ text-align: center;
565
+ margin-bottom: 0.5em;
566
+ color: #c9d1d9;
567
+ }
568
+
569
+ /* Key Points box */
570
+ .vimd-keypoints {
571
+ background-color: #161b22;
572
+ border: 1px solid #30363d;
573
+ border-radius: 6px;
574
+ padding: 1em;
575
+ margin: 1em 0;
576
+ }
577
+
578
+ .vimd-keypoints h2 {
579
+ font-size: 1.1em;
580
+ margin-top: 0;
581
+ margin-bottom: 0.5em;
582
+ color: #c9d1d9;
583
+ }
584
+
585
+ .vimd-keypoints ul {
586
+ margin: 0;
587
+ padding-left: 1.5em;
588
+ }
589
+
590
+ .vimd-keypoints li {
591
+ margin-bottom: 0.3em;
592
+ }
593
+
594
+ /* Abstract section */
595
+ .vimd-abstract {
596
+ border-left: 4px solid #58a6ff;
597
+ padding-left: 1em;
598
+ margin: 1em 0;
599
+ }
600
+
601
+ .vimd-abstract h2 {
602
+ font-size: 1.1em;
603
+ margin-top: 0;
604
+ margin-bottom: 0.5em;
605
+ color: #c9d1d9;
606
+ }
607
+
608
+ .vimd-abstract p {
609
+ margin: 0;
610
+ text-align: justify;
611
+ }
612
+
519
613
  /* Responsive */
520
614
  @media (max-width: 768px) {
521
615
  body {