Skip to content

Commit c12d625

Browse files
committed
fix: localized remaining assets and removed discord widget
1 parent bff6c1d commit c12d625

File tree

12 files changed

+400
-53
lines changed

12 files changed

+400
-53
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ logs
2727
.history
2828

2929
# Project
30+
.private
3031
public/assets
31-
TODO.md
32+
package-lock.json

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shamefully-hoist=true

app/pages/blog/index.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ useSeoMeta({
1414
ogDescription: description
1515
})
1616
17+
// TODO: Figure out OgImage component usage in static builds
1718
if (import.meta.client) defineOgImageComponent('myOgImage')
1819
</script>
1920

@@ -33,7 +34,7 @@ if (import.meta.client) defineOgImageComponent('myOgImage')
3334
:icon="post.icon"
3435
:title="post.title"
3536
:description="post.description"
36-
:image="post.image"
37+
:image="{ src: useRuntimeConfig().public.siteUrl + post.image.src }"
3738
:date="new Date(post.date).toLocaleDateString('en', { year: 'numeric', month: 'short', day: 'numeric' })"
3839
:authors="post.authors"
3940
:badge="post.badge"

app/pages/index.vue

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,7 @@ const batchTwo = computed(() => {
3737
return contributors.value.slice(mid)
3838
})
3939
40-
const discordWidgetSrc = computed(() => {
41-
const widgetId = page.value?.connect?.discordWidgetId
42-
const color = useColorMode().value === 'dark' ? 'light' : 'dark'
43-
44-
return widgetId ? `https://discord.com/widget?id=${widgetId}&theme=${color}` : undefined
45-
})
46-
47-
const isClient = ref(false)
48-
4940
onMounted(async () => {
50-
isClient.value = true
51-
5241
try {
5342
projects.value = dataStore.getProjects({
5443
itemsToShow: page.value?.projects?.itemsToShow || 6,
@@ -250,17 +239,35 @@ onMounted(async () => {
250239
<UPageSection
251240
v-if="page.connect"
252241
v-bind="page.connect"
242+
:ui="{
243+
features: 'block'
244+
}"
253245
>
254-
<div class="w-full h-[524px] rounded-lg shadow-2xl ring ring-default overflow-hidden relative">
255-
<USkeleton class="absolute inset-0 w-full h-full z-0" />
246+
<template #features>
247+
<UButton
248+
v-if="page.connect.button"
249+
v-bind="page.connect.button"
250+
class="bg-[#5865F2]"
251+
color="neutral"
252+
variant="subtle"
253+
size="xl"
254+
/>
255+
</template>
256256

257-
<iframe
258-
v-if="isClient && discordWidgetSrc"
259-
:src="discordWidgetSrc"
260-
allowtransparency="true"
261-
frameborder="0"
262-
sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
263-
class="absolute inset-0 w-full h-full z-10 transition-opacity duration-300"
257+
<div
258+
class="w-full h-[524px] rounded-lg shadow-2xl ring ring-default overflow-hidden relative flex items-center justify-center"
259+
>
260+
<NuxtImg
261+
v-if="page.connect.image && page.connect.image.src"
262+
:src="useRuntimeConfig().public.siteUrl + page.connect.image.src"
263+
:srcset="useRuntimeConfig().public.siteUrl + page.connect.image.src"
264+
:alt="page.connect.image.alt"
265+
class="absolute inset-0 w-full h-full object-cover"
266+
/>
267+
268+
<USkeleton
269+
v-else
270+
class="absolute inset-0 w-full h-full"
264271
/>
265272
</div>
266273
</UPageSection>

bun.lock

Lines changed: 81 additions & 8 deletions
Large diffs are not rendered by default.

content.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ const collections = {
119119
reverse: z.boolean().optional(),
120120
orientation: z.enum(orientationEnum).optional(),
121121
icon: z.string().optional(),
122-
discordWidgetId: z.string().optional()
122+
image: createImageSchema().optional(),
123+
button: createButtonSchema().optional()
123124
}).optional()
124125
})
125126
}),

content/0.index.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,11 @@ connect:
6565
icon: i-lucide-spline
6666
title: Connect With Us
6767
description: Have questions or feedback? We'd love to hear from you!
68-
discordWidgetId: "737206408482914387"
68+
image:
69+
src: /assets/images/connect-cover.jpg
70+
alt: Discord Community
71+
button:
72+
label: Join our Discord
73+
icon: i-simple-icons-discord
74+
to: https://discord.gg/mMrxAqaa3W
75+
target: _blank

content/2.download.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ download:
1212
title: Download
1313
description: Find the latest releases of our software and tools.
1414
items:
15-
- icon: i-simple-icons:windows
15+
- icon: i-simple-icons-windows
1616
title: Windows
1717
description: Download the latest version for Windows.
1818
items:
@@ -22,7 +22,7 @@ download:
2222
- icon: i-lucide-download
2323
label: Library
2424
repoName: projectm
25-
- icon: i-simple-icons:linux
25+
- icon: i-simple-icons-linux
2626
title: Linux
2727
description: Download the latest version for Linux.
2828
items:
@@ -32,7 +32,7 @@ download:
3232
- icon: i-lucide-download
3333
label: Library
3434
repoName: projectm
35-
- icon: i-simple-icons:apple
35+
- icon: i-simple-icons-apple
3636
title: macOS
3737
description: Download the latest version for macOS.
3838
items:

nuxt.config.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,50 @@ export default defineNuxtConfig({
5656
braceStyle: '1tbs'
5757
}
5858
}
59-
}
59+
},
6060

6161
// image: {
6262
// domains: ['projectm-visualizer.org']
63-
// }
63+
// },
64+
65+
icon: {
66+
provider: 'none',
67+
serverBundle: false,
68+
clientBundle: {
69+
scan: true,
70+
icons: [
71+
'lucide:menu',
72+
'lucide:chevron-down',
73+
'lucide:arrow-up-right',
74+
'lucide:arrow-right',
75+
'lucide:x',
76+
'lucide:hash',
77+
'lucide:sun',
78+
'lucide:moon',
79+
'lucide:book',
80+
'lucide:book-open',
81+
'lucide:book-text',
82+
'lucide:code-xml',
83+
'lucide:credit-card',
84+
'lucide:download',
85+
'lucide:equal-approximately',
86+
'lucide:folder-root',
87+
'lucide:git-fork',
88+
'lucide:newspaper',
89+
'lucide:pencil',
90+
'lucide:spline',
91+
'lucide:star',
92+
'simple-icons:apple',
93+
'simple-icons:codesandbox',
94+
'simple-icons:discord',
95+
'simple-icons:github',
96+
'simple-icons:linux',
97+
'simple-icons:mastodon',
98+
'simple-icons:stackblitz',
99+
'simple-icons:windows',
100+
'simple-icons:x',
101+
'simple-icons:youtube'
102+
]
103+
}
104+
}
64105
})

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"push-secrets": "bun run ./scripts/push-secrets.ts"
2525
},
2626
"dependencies": {
27-
"@iconify-json/lucide": "^1.2.47",
27+
"@iconify-json/lucide": "^1.2.49",
2828
"@iconify-json/simple-icons": "^1.2.38",
2929
"@nuxt/content": "^3.5.1",
3030
"@nuxt/image": "^1.10.0",
@@ -52,6 +52,7 @@
5252
"eslint": "^9.28.0",
5353
"libsodium-wrappers": "^0.7.15",
5454
"lint-staged": "^16.1.1",
55+
"node-gyp": "^11.2.0",
5556
"octokit": "^5.0.3",
5657
"semantic-release": "^24.2.5",
5758
"simple-git-hooks": "^2.13.0",

scripts/extract-icons.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// extract-icons.ts
2+
// Extract icons from the project and add to nuxt.config.ts icons
3+
// - arguments:
4+
// - options:
5+
// - "--dirs, -d" (comma-separated directories to scan, default: './app,./content,./shared')
6+
// - "--write, -w" (write changes to nuxt.config.ts, default: false)
7+
8+
import { join, extname } from 'node:path'
9+
import { readdirSync, statSync } from 'node:fs'
10+
11+
// ---------- Config & Constants ----------
12+
13+
// const NUXT_CONFIG_FILE = 'nuxt.config.ts'
14+
// Match only icons that start with "i-" and follow the pattern: i-[namespace]-[icon-name]
15+
const ICON_REGEX = /\bi-([\w]+-[\w-]+)\b/g
16+
const VALID_EXTENSIONS = ['.yml', '.yaml', '.json', '.md', '.vue', '.ts']
17+
const DIRS = ['./app', './content', './shared']
18+
19+
// ---------- Arg Parser ----------
20+
21+
function getArgValue(args: string[], long: string, short: string, fallback?: string): string | undefined {
22+
const index = args.indexOf(long) !== -1 ? args.indexOf(long) : args.indexOf(short)
23+
return index !== -1 && args[index + 1] && !args[index + 1]?.startsWith('-')
24+
? args[index + 1]
25+
: fallback
26+
}
27+
28+
function parseArgs() {
29+
const args = Bun.argv.slice(2)
30+
const dirs = getArgValue(args, '--dirs', '-d', DIRS.join(','))
31+
?.split(',')
32+
.map(dir => dir.trim())
33+
.filter(Boolean) || DIRS
34+
const write = args.includes('--write') || args.includes('-w')
35+
36+
if (dirs.length === 0) {
37+
console.error('❌ No directories provided. Use --dirs or -d to specify directories.')
38+
process.exit(1)
39+
}
40+
41+
return {
42+
dirs,
43+
write
44+
}
45+
}
46+
47+
// ---------- Icon Extraction ----------
48+
49+
async function extractIconsFromFile(filePath: string, icons: Set<string>) {
50+
const content = await Bun.file(filePath).text()
51+
let match: RegExpExecArray | null
52+
while ((match = ICON_REGEX.exec(content))) {
53+
if (match[1]) {
54+
icons.add(match[1])
55+
}
56+
}
57+
}
58+
59+
async function scanDirRecursively(dir: string, icons: Set<string>) {
60+
for (const entry of readdirSync(dir)) {
61+
const fullPath = join(dir, entry)
62+
const stats = statSync(fullPath)
63+
64+
if (stats.isDirectory()) {
65+
await scanDirRecursively(fullPath, icons)
66+
} else if (stats.isFile() && VALID_EXTENSIONS.includes(extname(fullPath))) {
67+
await extractIconsFromFile(fullPath, icons)
68+
}
69+
}
70+
}
71+
72+
// ---------- Nuxt Config Update ----------
73+
74+
// TODO: Implement this function to update the Nuxt config file with the extracted icons
75+
// without overwriting existing icons.
76+
// async function updateNuxtConfig(icons: string[]) {
77+
// const nuxtConfigPath = join(process.cwd(), NUXT_CONFIG_FILE)
78+
// const config = await Bun.file(nuxtConfigPath).text()
79+
80+
// const mergedIcons = new Set([
81+
// ...(config.icon?.clientBundle?.icons || []),
82+
// ...icons
83+
// ])
84+
85+
// config.icon.clientBundle.icons = mergedIcons
86+
87+
// await Bun.write(nuxtConfigPath, config)
88+
// console.log(`✅ Updated ${NUXT_CONFIG_FILE} with ${icons.length} icons.`)
89+
// }
90+
91+
// ---------- Format ----------
92+
93+
function cleanIcons(icons: Set<string>): string[] {
94+
return Array.from(icons)
95+
.map(icon => icon.trim())
96+
.filter(icon => icon.length > 0 && !icon.includes(' '))
97+
.map(icon => icon.replace(/_/g, '-'))
98+
.map((icon) => {
99+
const lastDash = icon.lastIndexOf('-')
100+
return lastDash !== -1
101+
? icon.slice(0, lastDash) + ':' + icon.slice(lastDash + 1)
102+
: icon
103+
})
104+
.filter((icon, index, self) => self.indexOf(icon) === index)
105+
.sort((a, b) => a.localeCompare(b))
106+
}
107+
// ---------- Main ----------
108+
109+
async function main() {
110+
const { dirs, write } = parseArgs()
111+
const icons = new Set<string>()
112+
113+
for (const dir of dirs) {
114+
await scanDirRecursively(dir, icons)
115+
}
116+
117+
const sortedIcons = cleanIcons(icons)
118+
console.log(`🔍 Found ${sortedIcons.length} styled icons:`)
119+
console.log(sortedIcons.map(i => ` '${i}'`).join(',\n'))
120+
121+
if (write) {
122+
// await updateNuxtConfig(sortedIcons)
123+
}
124+
}
125+
126+
main().catch((err) => {
127+
console.error('❌ Unexpected error:', err)
128+
process.exit(1)
129+
})

0 commit comments

Comments
 (0)