@markuxt/markuxt 0.1.4

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.
Files changed (94) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +168 -0
  3. package/app.config.d.ts +33 -0
  4. package/nuxt.config.ts +170 -0
  5. package/package.json +43 -0
  6. package/src/components/AppFooter.vue +225 -0
  7. package/src/components/AppHeader.vue +342 -0
  8. package/src/components/Hero.vue +438 -0
  9. package/src/components/Icon.vue +131 -0
  10. package/src/components/LanguageSwitcher.vue +71 -0
  11. package/src/components/MemberCard.vue +198 -0
  12. package/src/components/MembersGrid.vue +129 -0
  13. package/src/components/MermaidDiagram.vue +99 -0
  14. package/src/components/NewsCard.vue +119 -0
  15. package/src/components/PublicationCard.vue +245 -0
  16. package/src/components/SectionTitle.vue +75 -0
  17. package/src/components/content/ProseImg.vue +29 -0
  18. package/src/components/content/ProsePre.vue +58 -0
  19. package/src/components/content/ProseVideo.vue +45 -0
  20. package/src/composables/resolveContentImage.ts +35 -0
  21. package/src/content-transformers/binary-assets.ts +20 -0
  22. package/src/error.vue +58 -0
  23. package/src/layouts/default.vue +37 -0
  24. package/src/middleware/navigation-guard.ts +22 -0
  25. package/src/pages/index.vue +232 -0
  26. package/src/pages/members/[...slug].vue +542 -0
  27. package/src/pages/members/index.vue +147 -0
  28. package/src/pages/news/[...slug].vue +280 -0
  29. package/src/pages/news/index.vue +102 -0
  30. package/src/pages/positions/[...slug].vue +425 -0
  31. package/src/pages/positions/index.vue +266 -0
  32. package/src/pages/projects/[...slug].vue +441 -0
  33. package/src/pages/projects/index.vue +499 -0
  34. package/src/pages/publications/[...slug].vue +435 -0
  35. package/src/pages/publications/index.vue +145 -0
  36. package/src/plugins/mathml-components.ts +33 -0
  37. package/src/plugins/suppress-warnings.ts +40 -0
  38. package/src/public/_markuxt/components/AppFooter.vue +225 -0
  39. package/src/public/_markuxt/components/AppHeader.vue +342 -0
  40. package/src/public/_markuxt/components/Hero.vue +430 -0
  41. package/src/public/_markuxt/components/Icon.vue +131 -0
  42. package/src/public/_markuxt/components/LanguageSwitcher.vue +71 -0
  43. package/src/public/_markuxt/components/MemberCard.vue +198 -0
  44. package/src/public/_markuxt/components/MembersGrid.vue +129 -0
  45. package/src/public/_markuxt/components/MermaidDiagram.vue +99 -0
  46. package/src/public/_markuxt/components/NewsCard.vue +119 -0
  47. package/src/public/_markuxt/components/PublicationCard.vue +245 -0
  48. package/src/public/_markuxt/components/SectionTitle.vue +75 -0
  49. package/src/public/_markuxt/components/content/ProseImg.vue +29 -0
  50. package/src/public/_markuxt/components/content/ProsePre.vue +58 -0
  51. package/src/public/_markuxt/components/content/ProseVideo.vue +45 -0
  52. package/src/public/_markuxt/composables/resolveContentImage.ts +35 -0
  53. package/src/public/_markuxt/content-transformers/binary-assets.ts +20 -0
  54. package/src/public/_markuxt/error.vue +58 -0
  55. package/src/public/_markuxt/layouts/default.vue +37 -0
  56. package/src/public/_markuxt/middleware/navigation-guard.ts +22 -0
  57. package/src/public/_markuxt/pages/index.vue +232 -0
  58. package/src/public/_markuxt/pages/members/[...slug].vue +542 -0
  59. package/src/public/_markuxt/pages/members/index.vue +147 -0
  60. package/src/public/_markuxt/pages/news/[...slug].vue +280 -0
  61. package/src/public/_markuxt/pages/news/index.vue +102 -0
  62. package/src/public/_markuxt/pages/positions/[...slug].vue +425 -0
  63. package/src/public/_markuxt/pages/positions/index.vue +266 -0
  64. package/src/public/_markuxt/pages/projects/[...slug].vue +441 -0
  65. package/src/public/_markuxt/pages/projects/index.vue +499 -0
  66. package/src/public/_markuxt/pages/publications/[...slug].vue +435 -0
  67. package/src/public/_markuxt/pages/publications/index.vue +145 -0
  68. package/src/public/_markuxt/plugins/mathml-components.ts +33 -0
  69. package/src/public/_markuxt/plugins/suppress-warnings.ts +40 -0
  70. package/src/public/_markuxt/server/plugins/content-locale.ts +47 -0
  71. package/src/public/_markuxt/server/plugins/fix-content-anchors.ts +63 -0
  72. package/src/public/_markuxt/styles/_animations.css +99 -0
  73. package/src/public/_markuxt/styles/_base.css +31 -0
  74. package/src/public/_markuxt/styles/_code.css +109 -0
  75. package/src/public/_markuxt/styles/_components.css +109 -0
  76. package/src/public/_markuxt/styles/_layout.css +220 -0
  77. package/src/public/_markuxt/styles/_markdown.css +52 -0
  78. package/src/public/_markuxt/styles/_tokens.css +62 -0
  79. package/src/public/_markuxt/styles/_typography.css +144 -0
  80. package/src/public/_markuxt/styles/_utilities.css +110 -0
  81. package/src/public/_markuxt/styles/main.css +784 -0
  82. package/src/public/images/logo.png +0 -0
  83. package/src/server/plugins/content-locale.ts +47 -0
  84. package/src/server/plugins/fix-content-anchors.ts +63 -0
  85. package/src/styles/_animations.css +99 -0
  86. package/src/styles/_base.css +31 -0
  87. package/src/styles/_code.css +109 -0
  88. package/src/styles/_components.css +109 -0
  89. package/src/styles/_layout.css +220 -0
  90. package/src/styles/_markdown.css +52 -0
  91. package/src/styles/_tokens.css +62 -0
  92. package/src/styles/_typography.css +144 -0
  93. package/src/styles/_utilities.css +110 -0
  94. package/src/styles/main.css +784 -0
@@ -0,0 +1,232 @@
1
+ <template>
2
+ <div class="home-page">
3
+ <Hero />
4
+
5
+ <!-- Latest News -->
6
+ <section class="section" v-if="latestNews.length > 0">
7
+ <div class="container">
8
+ <SectionTitle
9
+ :title="t('home.latestNews')"
10
+ :description="t('home.newsDescription')"
11
+ align="center"
12
+ />
13
+ <div class="news-grid">
14
+ <NewsCard
15
+ v-for="item in latestNews"
16
+ :key="item._path"
17
+ :news="item"
18
+ />
19
+ </div>
20
+ <div class="section__actions" v-if="hasMoreNews">
21
+ <NuxtLink to="/news" class="btn btn-secondary">
22
+ {{ t('home.viewAllNews') }}
23
+ </NuxtLink>
24
+ </div>
25
+ </div>
26
+ </section>
27
+
28
+ <!-- Featured Members -->
29
+ <section class="section" v-if="featuredMembers.length > 0">
30
+ <div class="container">
31
+ <SectionTitle
32
+ :overline="t('home.ourTeam')"
33
+ :title="t('home.meetMembers')"
34
+ :description="t('home.teamDescription')"
35
+ align="center"
36
+ />
37
+ <MembersGrid :members="featuredMembers" :groupBy="false" />
38
+ <div class="section__actions">
39
+ <NuxtLink to="/members" class="btn btn-primary">
40
+ {{ t('home.viewAllMembers') }}
41
+ </NuxtLink>
42
+ </div>
43
+ </div>
44
+ </section>
45
+
46
+ <!-- Research Areas -->
47
+ <section class="section section--alt" v-if="researchAreas.length > 0">
48
+ <div class="container">
49
+ <SectionTitle
50
+ :overline="t('home.research')"
51
+ :title="t('home.researchAreas')"
52
+ align="center"
53
+ />
54
+ <div class="research-areas">
55
+ <div class="research-card" v-for="(area, index) in researchAreas" :key="index">
56
+ <span class="research-card__icon"><component class="icon-inline" :is="area.component" theme="outline" :size="28" fill="white" :stroke-width="3"/></span>
57
+ <h3 class="research-card__title">{{ area.title }}</h3>
58
+ <p class="research-card__description">{{ area.description }}</p>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </section>
63
+ </div>
64
+ </template>
65
+
66
+ <script setup lang="ts">
67
+ import { resolveComponent } from 'vue'
68
+
69
+ const { t } = useI18n()
70
+ const appConfig = useAppConfig()
71
+
72
+ // Fetch latest news
73
+ const { data: allNews } = await useAsyncData('home-news', () =>
74
+ queryContent('/news')
75
+ .where({ _hidden: { $ne: true } })
76
+ .sort({ date: -1 })
77
+ .limit(3)
78
+ .where({ _extension: 'md' }).find()
79
+ )
80
+
81
+ const latestNews = computed(() => allNews.value || [])
82
+ const hasMoreNews = computed(() => latestNews.value.length >= 3)
83
+
84
+ // Fetch featured members
85
+ const { data: allMembers } = await useAsyncData('home-members', () =>
86
+ queryContent('/members')
87
+ .where({ category: 'staff', _hidden: { $ne: true } })
88
+ .limit(4)
89
+ .where({ _extension: 'md' }).find()
90
+ )
91
+
92
+ const featuredMembers = computed(() => {
93
+ return (allMembers.value || []).map(member => ({
94
+ ...member,
95
+ slug: member._path?.split('/').pop() || member.slug,
96
+ name: member.name || member.title || 'Unnamed Member'
97
+ }))
98
+ })
99
+
100
+ interface ResearchAreaConfig {
101
+ icon: string
102
+ titleKey: string
103
+ descKey: string
104
+ }
105
+
106
+ // Research areas — driven by app.config, icons resolved by consuming project
107
+ const researchAreas = computed(() => {
108
+ const areas = (appConfig.markuxt as Record<string, any>)?.researchAreas as ResearchAreaConfig[] || []
109
+ return areas.map((area) => ({
110
+ title: t(area.titleKey),
111
+ description: t(area.descKey),
112
+ component: resolveComponent(area.icon),
113
+ }))
114
+ })
115
+
116
+ useHead({
117
+ title: t('home.pageTitle')
118
+ })
119
+ </script>
120
+
121
+ <style scoped>
122
+ .home-page {
123
+ padding-top: 0;
124
+ }
125
+
126
+ .section--alt {
127
+ background: linear-gradient(180deg, var(--color-bg-alt) 0%, var(--color-bg) 100%);
128
+ }
129
+
130
+ .news-grid {
131
+ display: grid;
132
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
133
+ gap: var(--spacing-xl);
134
+ margin-bottom: var(--spacing-xl);
135
+ }
136
+
137
+ .section__actions {
138
+ display: flex;
139
+ justify-content: center;
140
+ margin-top: var(--spacing-xl);
141
+ }
142
+
143
+ /* Research Areas */
144
+ .research-areas {
145
+ display: grid;
146
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
147
+ gap: var(--spacing-xl);
148
+ position: relative;
149
+ }
150
+
151
+ .research-areas::before {
152
+ content: '';
153
+ position: absolute;
154
+ inset: 0;
155
+ background-image:
156
+ linear-gradient(rgba(10, 37, 64, 0.03) 1px, transparent 1px),
157
+ linear-gradient(90deg, rgba(10, 37, 64, 0.03) 1px, transparent 1px);
158
+ background-size: 20px 20px;
159
+ opacity: 0.5;
160
+ pointer-events: none;
161
+ z-index: 0;
162
+ }
163
+
164
+ .research-card {
165
+ background: var(--color-bg-alt);
166
+ border-radius: var(--radius-xl);
167
+ padding: var(--spacing-xl);
168
+ text-align: center;
169
+ border: 1px solid var(--color-border);
170
+ transition: all var(--transition-base);
171
+ position: relative;
172
+ overflow: hidden;
173
+ }
174
+
175
+ .research-card:hover {
176
+ transform: translateY(-8px);
177
+ box-shadow: var(--shadow-xl);
178
+ border-color: var(--color-secondary);
179
+ }
180
+
181
+ .research-card:hover .research-card__icon {
182
+ transform: scale(1.1) rotate(5deg);
183
+ }
184
+
185
+ .research-card__icon {
186
+ width: 56px;
187
+ height: 56px;
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ margin: 0 auto var(--spacing-xl);
192
+ background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-secondary) 100%);
193
+ border-radius: var(--radius-full);
194
+ position: relative;
195
+ z-index: 1;
196
+ }
197
+
198
+ .research-card__icon :deep(.icon-container) {
199
+ position: relative;
200
+ z-index: 2;
201
+ }
202
+
203
+ .research-card__title {
204
+ font-family: var(--font-display);
205
+ font-size: 1.25rem;
206
+ font-weight: 600;
207
+ color: var(--color-primary);
208
+ margin-bottom: var(--spacing-sm);
209
+ }
210
+
211
+ .research-card__description {
212
+ font-size: 0.9375rem;
213
+ color: var(--color-text-muted);
214
+ line-height: 1.6;
215
+ }
216
+
217
+ /* Responsive */
218
+ @media (max-width: 768px) {
219
+ .research-areas {
220
+ grid-template-columns: 1fr;
221
+ }
222
+
223
+ .research-card {
224
+ padding: var(--spacing-lg);
225
+ }
226
+
227
+ .research-card__icon {
228
+ width: 48px;
229
+ height: 48px;
230
+ }
231
+ }
232
+ </style>