mirror of
https://github.com/modrinth/code.git
synced 2026-08-30 11:36:05 +00:00
start new website + layouts lib
This commit is contained in:
@@ -14,7 +14,7 @@ Read `packages/ui/AGENTS.md` in full.
|
||||
3. Treat the result as reference code and adapt it to the Modrinth codebase.
|
||||
4. Map Figma color variables to the applicable `surface-*` and `text-*` tokens. Do not use aliased Figma names directly.
|
||||
5. Reuse applicable components from `packages/ui/src/components/` before creating new ones. Also refer to `standards/frontend/COMPONENT_STRUCTURE.md`
|
||||
6. Read `packages/assets/styles/variables.scss` when Figma does not supply a required token.
|
||||
6. Read `packages/assets/styles/variables.css` when Figma does not supply a required token.
|
||||
7. Use exact spacing values from the design.
|
||||
8. Implement the result as a Vue SFC with Tailwind classes and the existing component library.
|
||||
|
||||
|
||||
Vendored
+2
@@ -35,6 +35,8 @@
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/ui/src/locales",
|
||||
"apps/frontend/src/locales",
|
||||
"apps/website/src/locales",
|
||||
"packages/layouts/src/locales",
|
||||
"packages/moderation/src/locales"
|
||||
],
|
||||
"i18n-ally.pathMatcher": "{locale}/index.{ext}",
|
||||
|
||||
@@ -184,7 +184,7 @@ img {
|
||||
}
|
||||
}
|
||||
|
||||
@import '@modrinth/assets/omorphia.scss';
|
||||
@import '@modrinth/assets/omorphia.css';
|
||||
|
||||
input {
|
||||
border-radius: var(--size-rounded-sm);
|
||||
|
||||
@@ -25,8 +25,8 @@ export default defineConfig({
|
||||
replacesTitle: true,
|
||||
},
|
||||
customCss: [
|
||||
'@modrinth/assets/styles/variables.scss',
|
||||
'@modrinth/assets/styles/inter.scss',
|
||||
'@modrinth/assets/styles/variables.css',
|
||||
'@modrinth/assets/styles/inter.css',
|
||||
'./src/styles/modrinth.css',
|
||||
],
|
||||
plugins: [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '@modrinth/assets/styles/reset.scss';
|
||||
@import '@modrinth/assets/styles/reset.css';
|
||||
|
||||
html {
|
||||
--dark-color-text: #b0bac5;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
@@ -0,0 +1,7 @@
|
||||
**/.nuxt
|
||||
**/dist
|
||||
**/.output
|
||||
**/.data
|
||||
**/.wrangler
|
||||
src/locales/**
|
||||
src/assets/**/*.svg
|
||||
@@ -0,0 +1,75 @@
|
||||
# Nuxt Minimal Starter
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
@@ -0,0 +1,9 @@
|
||||
import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
|
||||
export default config.append([
|
||||
{
|
||||
rules: {
|
||||
'import/no-unresolved': 'off',
|
||||
'no-undef': 'off',
|
||||
},
|
||||
},
|
||||
])
|
||||
@@ -0,0 +1,28 @@
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
srcDir: 'src/',
|
||||
compatibilityDate: '2025-07-15',
|
||||
devtools: { enabled: true },
|
||||
devServer: {
|
||||
port: 42069,
|
||||
},
|
||||
app: {
|
||||
head: {
|
||||
title: 'Modrinth 2',
|
||||
htmlAttrs: {
|
||||
lang: 'en',
|
||||
},
|
||||
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
|
||||
},
|
||||
},
|
||||
future: {
|
||||
compatibilityVersion: 5,
|
||||
},
|
||||
css: ['~/assets/styles/styles.css'],
|
||||
postcss: {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@modrinth/website",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare",
|
||||
"lint": "eslint . && prettier --check .",
|
||||
"fix": "eslint . --fix && prettier --write .",
|
||||
"intl:extract": "formatjs extract \"src/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
|
||||
"intl:prune-local": "pnpm -w scripts i18n-icu-contract prune-local --scope apps/website"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modrinth/assets": "workspace:*",
|
||||
"@modrinth/layouts": "workspace:*",
|
||||
"@modrinth/ui": "workspace:*",
|
||||
"intl-messageformat": "^10.7.7",
|
||||
"lru-cache": "^11.2.4",
|
||||
"nuxt": "^4.5.2",
|
||||
"vue": "^3.5.41",
|
||||
"vue-router": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/cli": "^6.2.12",
|
||||
"@modrinth/tooling-config": "workspace:*",
|
||||
"autoprefixer": "^10.5.4",
|
||||
"postcss": "^8.5.26",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"vite-tsconfig-paths": "^6.1.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { NuxtModrinthClient } from '@modrinth/api-client'
|
||||
import { provideModrinthClient, providePageContext } from '@modrinth/ui'
|
||||
|
||||
provideModrinthClient(
|
||||
new NuxtModrinthClient({
|
||||
labrinthBaseUrl: 'https://api.modrinth.com',
|
||||
}),
|
||||
)
|
||||
|
||||
providePageContext({
|
||||
hierarchicalSidebarAvailable: ref(false),
|
||||
showAds: ref(false),
|
||||
adConsentAvailable: ref(false),
|
||||
floatingActionBarOffsets: {
|
||||
left: ref(0),
|
||||
right: ref(0),
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="page-layout">
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.page-layout {
|
||||
@apply max-w-[min(80rem,100%-1.5rem)] mx-auto h-[100dvh] pt-6;
|
||||
|
||||
&:has(#page-sidebar:not(:empty)) {
|
||||
@apply grid grid-cols-[1fr_300px];
|
||||
grid-template-areas: 'anything sidebar';
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
#page-sidebar {
|
||||
@apply pl-4 border-l border-surface-5;
|
||||
grid-area: sidebar;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,182 @@
|
||||
@import '@modrinth/ui/src/styles/tailwind-utilities.css';
|
||||
@import '@modrinth/assets/omorphia.css';
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
font-family: var(--font-standard, sans-serif), sans-serif;
|
||||
color-scheme: dark;
|
||||
--view-width: calc(100% - 5rem);
|
||||
--expanded-view-width: calc(100% - 13rem);
|
||||
--medal-promotion-bg: #000;
|
||||
--medal-promotion-bg-orange: rgba(208, 246, 255, 0.25);
|
||||
--medal-promotion-text-orange: #42abff;
|
||||
--medal-promotion-bg-gradient: linear-gradient(
|
||||
90deg,
|
||||
rgba(66, 170, 255, 0.15),
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
html.light-mode {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
body {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card-divider {
|
||||
background-color: var(--color-button-bg);
|
||||
border: none;
|
||||
color: var(--color-button-bg);
|
||||
height: 1px;
|
||||
margin: var(--gap-sm) 0;
|
||||
}
|
||||
|
||||
.no-wrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.no-select {
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
will-change: filter;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: flex;
|
||||
border-radius: var(--radius-md);
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
background-color: var(--color-bg);
|
||||
padding-block: var(--gap-sm);
|
||||
padding-inline: var(--gap-lg);
|
||||
width: min-content;
|
||||
|
||||
svg {
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
&.featured {
|
||||
background-color: var(--color-brand-highlight);
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: auto;
|
||||
scrollbar-color: var(--color-scrollbar) var(--color-bg);
|
||||
}
|
||||
|
||||
/* Chrome, Edge, and Safari */
|
||||
*::-webkit-scrollbar {
|
||||
width: 16px;
|
||||
border: 3px solid transparent;
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-scrollbar);
|
||||
border-radius: var(--radius-lg);
|
||||
border: 5px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.highlighted {
|
||||
box-shadow: 0 0 1rem var(--color-brand) !important;
|
||||
}
|
||||
|
||||
.gecko {
|
||||
background-color: var(--color-raised-bg);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
img {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.card-shadow {
|
||||
box-shadow: var(--shadow-card);
|
||||
}
|
||||
|
||||
input {
|
||||
border-radius: var(--size-rounded-sm);
|
||||
box-sizing: border-box;
|
||||
border: 2px solid transparent;
|
||||
/* safari iOS rounds inputs by default. set the appearance to none to prevent this */
|
||||
appearance: none !important;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-weight: var(--font-weight-regular);
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
background: var(--color-button-bg);
|
||||
color: var(--color-text);
|
||||
padding: 0.5rem 1rem;
|
||||
font-weight: var(--font-weight-medium);
|
||||
border: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow:
|
||||
var(--shadow-inset-sm),
|
||||
0 0 0 0 transparent;
|
||||
transition: box-shadow 0.1s ease-in-out;
|
||||
min-height: 36px;
|
||||
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
box-shadow:
|
||||
inset 0 0 0 transparent,
|
||||
0 0 0 0.25rem var(--color-brand-shadow);
|
||||
color: var(--color-button-text-active);
|
||||
}
|
||||
|
||||
&:disabled,
|
||||
&[disabled='true'] {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:focus::placeholder {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-button-text);
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts"></script>
|
||||
<template>
|
||||
all the fun stuff:
|
||||
<ul>
|
||||
<li>
|
||||
<NuxtLink to="/user/Prospector">User page</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { UserPage } from '@modrinth/layouts'
|
||||
|
||||
const { id } = useRoute().params
|
||||
</script>
|
||||
<template>
|
||||
<UserPage :user-id="id" />
|
||||
</template>
|
||||
@@ -0,0 +1,237 @@
|
||||
import { layoutsLocaleModules } from '@modrinth/layouts'
|
||||
import {
|
||||
type CrowdinMessages,
|
||||
I18N_INJECTION_KEY,
|
||||
type I18nContext,
|
||||
LOCALES,
|
||||
transformCrowdinMessages,
|
||||
uiLocaleModules,
|
||||
useDebugLogger,
|
||||
} from '@modrinth/ui'
|
||||
import IntlMessageFormat from 'intl-messageformat'
|
||||
import { LRUCache } from 'lru-cache'
|
||||
|
||||
const debug = useDebugLogger('i18n')
|
||||
const DEFAULT_LOCALE = 'en-US'
|
||||
|
||||
const websiteLocaleModules = import.meta.glob<{ default: CrowdinMessages }>(
|
||||
'../locales/*/index.json',
|
||||
{ eager: false },
|
||||
)
|
||||
|
||||
const messageCache = new LRUCache<string, Record<string, string>>({ max: 10 })
|
||||
const formatterCache = new LRUCache<string, IntlMessageFormat>({ max: 1000 })
|
||||
const loadingPromises = new Map<string, Promise<void>>()
|
||||
|
||||
type LocaleModules = Record<string, () => Promise<{ default: CrowdinMessages }>>
|
||||
|
||||
function findLocaleLoader(modules: LocaleModules, code: string) {
|
||||
for (const [path, loader] of Object.entries(modules)) {
|
||||
if (path.endsWith(`/${code}/index.json`)) {
|
||||
return loader
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function formatIcuMessage(msg: string, locale: string, values: Record<string, unknown>) {
|
||||
const cacheKey = `${locale}:${msg}`
|
||||
let formatter = formatterCache.get(cacheKey)
|
||||
|
||||
try {
|
||||
if (!formatter) {
|
||||
formatter = new IntlMessageFormat(msg, locale)
|
||||
formatterCache.set(cacheKey, formatter)
|
||||
}
|
||||
const result = formatter.format(values)
|
||||
if (import.meta.dev && typeof result !== 'string') {
|
||||
debug('formatIcuMessage: format returned non-string', typeof result)
|
||||
}
|
||||
return result as string
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadLocale(code: string): Promise<void> {
|
||||
if (messageCache.has(code)) {
|
||||
debug('loadLocale: already cached', code)
|
||||
return
|
||||
}
|
||||
|
||||
const existing = loadingPromises.get(code)
|
||||
if (existing) {
|
||||
debug('loadLocale: already loading', code)
|
||||
return existing
|
||||
}
|
||||
|
||||
debug('loadLocale: starting', code)
|
||||
|
||||
const promise = (async () => {
|
||||
const websiteLoader = findLocaleLoader(websiteLocaleModules, code)
|
||||
const uiLoader = findLocaleLoader(uiLocaleModules, code)
|
||||
const layoutsLoader = findLocaleLoader(layoutsLocaleModules, code)
|
||||
|
||||
debug('loadLocale: loaders found', {
|
||||
code,
|
||||
website: !!websiteLoader,
|
||||
ui: !!uiLoader,
|
||||
layouts: !!layoutsLoader,
|
||||
})
|
||||
|
||||
const [uiData, layoutsData, websiteData] = await Promise.all([
|
||||
uiLoader?.().catch((e) => {
|
||||
debug('loadLocale: ui loader failed', code, e)
|
||||
return null
|
||||
}),
|
||||
layoutsLoader?.().catch((e) => {
|
||||
debug('loadLocale: layouts loader failed', code, e)
|
||||
return null
|
||||
}),
|
||||
websiteLoader?.().catch((e) => {
|
||||
debug('loadLocale: website loader failed', code, e)
|
||||
return null
|
||||
}),
|
||||
])
|
||||
|
||||
debug('loadLocale: data loaded', {
|
||||
code,
|
||||
uiKeys: uiData ? Object.keys(uiData.default).length : 0,
|
||||
layoutsKeys: layoutsData ? Object.keys(layoutsData.default).length : 0,
|
||||
websiteKeys: websiteData ? Object.keys(websiteData.default).length : 0,
|
||||
})
|
||||
|
||||
const mergedMessages: Record<string, string> = {}
|
||||
if (uiData) Object.assign(mergedMessages, transformCrowdinMessages(uiData.default))
|
||||
if (layoutsData) Object.assign(mergedMessages, transformCrowdinMessages(layoutsData.default))
|
||||
if (websiteData) Object.assign(mergedMessages, transformCrowdinMessages(websiteData.default))
|
||||
|
||||
debug('loadLocale: merged', code, 'total keys:', Object.keys(mergedMessages).length)
|
||||
|
||||
if (Object.keys(mergedMessages).length > 0) {
|
||||
messageCache.set(code, mergedMessages)
|
||||
}
|
||||
})()
|
||||
|
||||
loadingPromises.set(code, promise)
|
||||
try {
|
||||
await promise
|
||||
} finally {
|
||||
loadingPromises.delete(code)
|
||||
}
|
||||
}
|
||||
|
||||
function parseAcceptLanguage(header: string): string | null {
|
||||
try {
|
||||
for (const lang of header
|
||||
.split(',')
|
||||
.map((l) => l.split(';')[0]?.trim())
|
||||
.filter(Boolean)) {
|
||||
const exact = LOCALES.find((loc) => loc.code === lang)
|
||||
if (exact) return exact.code
|
||||
const prefix = LOCALES.find((loc) => loc.code.startsWith(lang.split('-')[0] + '-'))
|
||||
if (prefix) return prefix.code
|
||||
}
|
||||
} catch {
|
||||
// Malformed header, ignore
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin({
|
||||
name: 'i18n',
|
||||
enforce: 'pre',
|
||||
async setup(nuxtApp) {
|
||||
const locale = useState<string>('i18n-locale', () => DEFAULT_LOCALE)
|
||||
const localeDir = computed(
|
||||
() => LOCALES.find((entry) => entry.code === locale.value)?.dir ?? 'ltr',
|
||||
)
|
||||
|
||||
function t(key: string, values?: Record<string, unknown>): string {
|
||||
const currentLocale = locale.value
|
||||
const localeMessages = messageCache.get(currentLocale)
|
||||
const fallbackMessages = messageCache.get(DEFAULT_LOCALE)
|
||||
const msg = localeMessages?.[key] ?? fallbackMessages?.[key]
|
||||
|
||||
if (!msg) {
|
||||
debug('t: key not found', {
|
||||
key,
|
||||
locale: currentLocale,
|
||||
hasLocaleMessages: !!localeMessages,
|
||||
hasFallbackMessages: !!fallbackMessages,
|
||||
})
|
||||
return key
|
||||
}
|
||||
|
||||
if (!values || Object.keys(values).length === 0) return msg
|
||||
|
||||
const formatted = formatIcuMessage(msg, currentLocale, values)
|
||||
if (formatted !== null) return formatted
|
||||
|
||||
const fallbackMsg = fallbackMessages?.[key]
|
||||
if (fallbackMsg && fallbackMsg !== msg) {
|
||||
return formatIcuMessage(fallbackMsg, DEFAULT_LOCALE, values) ?? fallbackMsg
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
async function setLocale(
|
||||
newLocale: string,
|
||||
{ persist = true }: { persist?: boolean } = {},
|
||||
): Promise<void> {
|
||||
debug('setLocale: called', { newLocale, currentLocale: locale.value })
|
||||
|
||||
if (!LOCALES.some((l) => l.code === newLocale)) {
|
||||
debug('setLocale: invalid locale', newLocale)
|
||||
return
|
||||
}
|
||||
|
||||
await loadLocale(newLocale)
|
||||
|
||||
debug('setLocale: loaded', {
|
||||
newLocale,
|
||||
cacheHas: messageCache.has(newLocale),
|
||||
cacheKeys: messageCache.get(newLocale)
|
||||
? Object.keys(messageCache.get(newLocale)!).length
|
||||
: 0,
|
||||
})
|
||||
|
||||
locale.value = newLocale
|
||||
if (persist) {
|
||||
useCookie('locale', { maxAge: 31536000, path: '/' }).value = newLocale
|
||||
}
|
||||
}
|
||||
|
||||
const cookieLocale = useCookie('locale').value
|
||||
let detectedLocale = DEFAULT_LOCALE
|
||||
if (cookieLocale && LOCALES.some((l) => l.code === cookieLocale)) {
|
||||
detectedLocale = cookieLocale
|
||||
debug('init: locale from cookie', detectedLocale)
|
||||
} else if (import.meta.server) {
|
||||
const acceptLang = useRequestHeaders(['accept-language'])['accept-language']
|
||||
if (acceptLang) {
|
||||
detectedLocale = parseAcceptLanguage(acceptLang) ?? DEFAULT_LOCALE
|
||||
debug('init: locale from Accept-Language', detectedLocale)
|
||||
}
|
||||
}
|
||||
|
||||
debug('init: detected locale', { detectedLocale, cookieLocale, isServer: import.meta.server })
|
||||
|
||||
await loadLocale(DEFAULT_LOCALE)
|
||||
if (detectedLocale !== DEFAULT_LOCALE) await loadLocale(detectedLocale)
|
||||
locale.value = detectedLocale
|
||||
|
||||
debug('init: complete', { locale: locale.value })
|
||||
|
||||
useHead({
|
||||
htmlAttrs: {
|
||||
lang: locale,
|
||||
dir: localeDir,
|
||||
},
|
||||
})
|
||||
|
||||
const context: I18nContext = { locale, t, setLocale }
|
||||
nuxtApp.vueApp.provide(I18N_INJECTION_KEY, context)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
// https://tanstack.com/query/v5/docs/framework/vue/examples/nuxt3
|
||||
import type { DehydratedState, VueQueryPluginOptions } from '@tanstack/vue-query'
|
||||
import { dehydrate, hydrate, QueryClient, VueQueryPlugin } from '@tanstack/vue-query'
|
||||
|
||||
import { defineNuxtPlugin, useState } from '#imports'
|
||||
|
||||
export default defineNuxtPlugin((nuxt) => {
|
||||
const vueQueryState = useState<DehydratedState | null>('vue-query')
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 10000,
|
||||
retry: (failureCount, error) => {
|
||||
const status = (error as any)?.statusCode ?? (error as any)?.status
|
||||
if (status !== undefined && status >= 400 && status < 500 && status !== 429) return false
|
||||
return failureCount < 3
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
const options: VueQueryPluginOptions = { queryClient }
|
||||
|
||||
nuxt.vueApp.use(VueQueryPlugin, options)
|
||||
|
||||
// Expose queryClient for middleware and composables
|
||||
nuxt.provide('queryClient', queryClient)
|
||||
|
||||
if (import.meta.server) {
|
||||
nuxt.hooks.hook('app:rendered', () => {
|
||||
vueQueryState.value = dehydrate(queryClient)
|
||||
})
|
||||
}
|
||||
|
||||
if (import.meta.client) {
|
||||
hydrate(queryClient, vueQueryState.value)
|
||||
}
|
||||
})
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,2 @@
|
||||
User-Agent: *
|
||||
Disallow:
|
||||
@@ -0,0 +1,14 @@
|
||||
import preset from '@modrinth/tooling-config/tailwind/tailwind-preset.ts'
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
'./src/**/*.{js,vue,ts,mdx}',
|
||||
'./src/app.vue',
|
||||
'../../packages/**/*.{js,vue,ts}',
|
||||
'!../../packages/**/node_modules/**',
|
||||
],
|
||||
presets: [preset],
|
||||
}
|
||||
|
||||
export default config
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.server.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.shared.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
+10
@@ -12,6 +12,11 @@ files:
|
||||
translation: /apps/frontend/src/locales/%locale%/%original_file_name%
|
||||
skip_untranslated_strings: true
|
||||
|
||||
# - source: /apps/website/src/locales/en-US/*.json
|
||||
# dest: /website/%original_file_name%
|
||||
# translation: /apps/website/src/locales/%locale%/%original_file_name%
|
||||
# skip_untranslated_strings: true
|
||||
|
||||
- source: /packages/ui/src/locales/en-US/*.json
|
||||
dest: /ui/%original_file_name%
|
||||
translation: /packages/ui/src/locales/%locale%/%original_file_name%
|
||||
@@ -22,5 +27,10 @@ files:
|
||||
translation: /packages/moderation/src/locales/%locale%/%original_file_name%
|
||||
skip_untranslated_strings: true
|
||||
|
||||
- source: /packages/layouts/src/locales/en-US/*.json
|
||||
dest: /layouts/%original_file_name%
|
||||
translation: /packages/layouts/src/locales/%locale%/%original_file_name%
|
||||
skip_untranslated_strings: true
|
||||
|
||||
project_id_env: CROWDIN_PROJECT_ID
|
||||
api_token_env: CROWDIN_PERSONAL_TOKEN
|
||||
|
||||
+76
-75
@@ -1,77 +1,78 @@
|
||||
{
|
||||
"name": "@modrinth/monorepo",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"web:dev": "pnpm i18n:coverage && turbo run dev --filter=@modrinth/frontend",
|
||||
"web:build": "turbo run build --filter=@modrinth/frontend",
|
||||
"app:dev": "turbo run dev --filter=@modrinth/app",
|
||||
"app:build": "turbo run build --filter=@modrinth/app",
|
||||
"docs:dev": "turbo run dev --filter=@modrinth/docs",
|
||||
"pages:build": "pnpm i18n:coverage && NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build",
|
||||
"build": "turbo run build --continue",
|
||||
"lint": "turbo run lint lint:ancillary --continue",
|
||||
"lint:ancillary": "prettier --check .github *.*",
|
||||
"test": "turbo run test --continue",
|
||||
"fix": "turbo run fix fix:ancillary --continue",
|
||||
"fix:ancillary": "prettier --write .github *.*",
|
||||
"ci": "turbo run lint test --continue",
|
||||
"prepr": "turbo run prepr --continue",
|
||||
"prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend",
|
||||
"prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config",
|
||||
"prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend",
|
||||
"prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend",
|
||||
"storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui storybook",
|
||||
"build-storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui build-storybook",
|
||||
"icons:add": "pnpm --filter @modrinth/assets icons:add",
|
||||
"i18n:coverage": "node scripts/run.mjs coverage-i18n --write packages/ui/src/layouts/wrapped/settings/language-settings/language-settings-coverage.generated.ts --quiet",
|
||||
"changelog:collect": "node scripts/run.mjs collect-changelog",
|
||||
"changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes",
|
||||
"scripts": "node scripts/run.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@crowdin/crowdin-api-client": "^1.55.2",
|
||||
"@formatjs/icu-messageformat-parser": "^2.11.4",
|
||||
"@modrinth/tooling-config": "workspace:*",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@types/node": "^24",
|
||||
"@typescript-eslint/typescript-estree": "^8.64.0",
|
||||
"@vue/compiler-dom": "^3.5.26",
|
||||
"@vue/compiler-sfc": "^3.5.26",
|
||||
"chalk": "^5.6.2",
|
||||
"if-ci": "^3.0.0",
|
||||
"keep-a-changelog": "^3.0.2",
|
||||
"prettier": "^3.3.2",
|
||||
"turbo": "^2.5.4",
|
||||
"vue": "^3.5.13",
|
||||
"yaml": "^2.8.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.2",
|
||||
"engines": {
|
||||
"node": ">=24.15.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch"
|
||||
},
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
"vite": "8",
|
||||
"esbuild": "0"
|
||||
}
|
||||
},
|
||||
"onlyBuiltDependencies": [
|
||||
"@parcel/watcher",
|
||||
"@sentry/cli",
|
||||
"core-js",
|
||||
"esbuild",
|
||||
"protobufjs",
|
||||
"sharp",
|
||||
"unrs-resolver",
|
||||
"vue-demi",
|
||||
"workerd"
|
||||
]
|
||||
},
|
||||
"prettier": "@modrinth/tooling-config/prettier.config.cjs"
|
||||
"name": "@modrinth/monorepo",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"new:dev": "turbo run dev --filter=@modrinth/website",
|
||||
"web:dev": "pnpm i18n:coverage && turbo run dev --filter=@modrinth/frontend",
|
||||
"web:build": "turbo run build --filter=@modrinth/frontend",
|
||||
"app:dev": "turbo run dev --filter=@modrinth/app",
|
||||
"app:build": "turbo run build --filter=@modrinth/app",
|
||||
"docs:dev": "turbo run dev --filter=@modrinth/docs",
|
||||
"pages:build": "pnpm i18n:coverage && NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build",
|
||||
"build": "turbo run build --continue",
|
||||
"lint": "turbo run lint lint:ancillary --continue",
|
||||
"lint:ancillary": "prettier --check .github *.*",
|
||||
"test": "turbo run test --continue",
|
||||
"fix": "turbo run fix fix:ancillary --continue",
|
||||
"fix:ancillary": "prettier --write .github *.*",
|
||||
"ci": "turbo run lint test --continue",
|
||||
"prepr": "turbo run prepr --continue",
|
||||
"prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend --filter=@modrinth/website",
|
||||
"prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/layouts --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config",
|
||||
"prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/website",
|
||||
"prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend",
|
||||
"storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui storybook",
|
||||
"build-storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui build-storybook",
|
||||
"icons:add": "pnpm --filter @modrinth/assets icons:add",
|
||||
"i18n:coverage": "node scripts/run.mjs coverage-i18n --write packages/ui/src/layouts/wrapped/settings/language-settings/language-settings-coverage.generated.ts --quiet",
|
||||
"changelog:collect": "node scripts/run.mjs collect-changelog",
|
||||
"changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes",
|
||||
"scripts": "node scripts/run.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@crowdin/crowdin-api-client": "^1.55.2",
|
||||
"@formatjs/icu-messageformat-parser": "^2.11.4",
|
||||
"@modrinth/tooling-config": "workspace:*",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@types/node": "^24",
|
||||
"@typescript-eslint/typescript-estree": "^8.64.0",
|
||||
"@vue/compiler-dom": "^3.5.26",
|
||||
"@vue/compiler-sfc": "^3.5.26",
|
||||
"chalk": "^5.6.2",
|
||||
"if-ci": "^3.0.0",
|
||||
"keep-a-changelog": "^3.0.2",
|
||||
"prettier": "^3.3.2",
|
||||
"turbo": "^2.5.4",
|
||||
"vue": "^3.5.13",
|
||||
"yaml": "^2.8.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.2",
|
||||
"engines": {
|
||||
"node": ">=24.15.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch"
|
||||
},
|
||||
"peerDependencyRules": {
|
||||
"allowedVersions": {
|
||||
"vite": "8",
|
||||
"esbuild": "0"
|
||||
}
|
||||
},
|
||||
"onlyBuiltDependencies": [
|
||||
"@parcel/watcher",
|
||||
"@sentry/cli",
|
||||
"core-js",
|
||||
"esbuild",
|
||||
"protobufjs",
|
||||
"sharp",
|
||||
"unrs-resolver",
|
||||
"vue-demi",
|
||||
"workerd"
|
||||
]
|
||||
},
|
||||
"prettier": "@modrinth/tooling-config/prettier.config.cjs"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* and automatically generated through the "pnpm run fix" command.
|
||||
*/
|
||||
|
||||
import './omorphia.scss'
|
||||
import './omorphia.css'
|
||||
|
||||
import _FourOhFourNotFound from './branding/404.svg?component'
|
||||
// Branding
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Create the variables used by everything */
|
||||
@import './styles/variables.css';
|
||||
/* Normalize styling across browsers to a standard stripped down form */
|
||||
@import './styles/normalize.css';
|
||||
|
||||
/* Add Omorphia base classes */
|
||||
@import './styles/classes.css';
|
||||
|
||||
/* Apply default styles */
|
||||
@import './styles/defaults.css';
|
||||
/* Apply code block highlighting styles */
|
||||
@import './styles/highlightjs.css';
|
||||
|
||||
/* Finally, apply accessibility-related global styling */
|
||||
@import './styles/accessibility.css';
|
||||
|
||||
/* Fonts */
|
||||
@import './styles/inter.css';
|
||||
@@ -1,18 +0,0 @@
|
||||
// Create the variables used by everything
|
||||
@import 'styles/variables';
|
||||
// Normalize styling across browsers to a standard stripped down form
|
||||
@import 'styles/normalize';
|
||||
|
||||
// Add Omorphia base classes
|
||||
@import 'styles/classes';
|
||||
|
||||
// Apply default styles
|
||||
@import 'styles/defaults';
|
||||
// Apply code block highlighting styles
|
||||
@import 'styles/highlightjs';
|
||||
|
||||
// Finally, apply accessibility-related global styling
|
||||
@import 'styles/accessibility';
|
||||
|
||||
// Fonts
|
||||
@import 'styles/inter';
|
||||
@@ -1,13 +1,15 @@
|
||||
// Bodies + Generic Global Styles
|
||||
/* Bodies + Generic Global Styles */
|
||||
|
||||
.universal-labels {
|
||||
.universal-labels,
|
||||
.universal-body,
|
||||
.card {
|
||||
label,
|
||||
.label {
|
||||
:where(.label__title) {
|
||||
display: block;
|
||||
margin-block: var(--gap-md) var(--gap-sm);
|
||||
|
||||
// Same styling as h3
|
||||
/* Same styling as h3 */
|
||||
color: var(--color-contrast);
|
||||
font-size: 1.17rem;
|
||||
font-weight: bold;
|
||||
@@ -38,9 +40,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.universal-body {
|
||||
@extend .universal-labels;
|
||||
|
||||
.universal-body,
|
||||
.card {
|
||||
> :where(input + *, .input-group + *, .chips + *, .input-div + *) {
|
||||
margin-block-start: var(--gap-md);
|
||||
}
|
||||
@@ -101,7 +102,7 @@
|
||||
}
|
||||
|
||||
@media screen and (max-width: 750px) {
|
||||
&:not(&.small) {
|
||||
&:not(.small) {
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
}
|
||||
@@ -187,28 +188,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
// CLICKABLES/BUTTONS
|
||||
/* CLICKABLES/BUTTONS */
|
||||
a:not(.no-click-animation),
|
||||
.clickable {
|
||||
.clickable,
|
||||
.button-base,
|
||||
.btn {
|
||||
transition:
|
||||
opacity 0.5s ease-in-out,
|
||||
filter 0.2s ease-in-out,
|
||||
scale 0.05s ease-in-out,
|
||||
outline 0.2s ease-in-out;
|
||||
|
||||
&:active:not(&:disabled) {
|
||||
&:active:not(:disabled) {
|
||||
scale: 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
.button-base {
|
||||
@extend .clickable;
|
||||
.button-base,
|
||||
.btn {
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
outline: 2px solid transparent;
|
||||
|
||||
&:focus-visible:not(&:disabled),
|
||||
&:hover:not(&:disabled) {
|
||||
&:focus-visible:not(:disabled),
|
||||
&:hover:not(:disabled) {
|
||||
cursor: pointer;
|
||||
|
||||
&:not(.btn-outline.btn-hover-filled, .btn-transparent) {
|
||||
@@ -216,7 +219,7 @@ a:not(.no-click-animation),
|
||||
}
|
||||
}
|
||||
|
||||
&:active:not(&:disabled, .btn-outline.btn-hover-filled, .btn-transparent) {
|
||||
&:active:not(:disabled, .btn-outline.btn-hover-filled, .btn-transparent) {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
@@ -240,17 +243,17 @@ a:not(.no-click-animation),
|
||||
transform 0.05s ease-in-out,
|
||||
outline 0.2s ease-in-out;
|
||||
|
||||
&:focus-visible:not(&.disabled),
|
||||
&:hover:not(&.disabled) {
|
||||
&:focus-visible:not(.disabled),
|
||||
&:hover:not(.disabled) {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
|
||||
&:active:not(&.disabled) {
|
||||
&:active:not(.disabled) {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
// For some reason this within the above block makes it universal and not only applied to children. SCSS bug maybe?
|
||||
&:active:not(&.disabled) button:not(&:disabled) {
|
||||
/* For some reason this within the above block makes it universal and not only applied to children. SCSS bug maybe? */
|
||||
&:active:not(.disabled) button:not(:disabled) {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
@@ -269,8 +272,6 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
.btn {
|
||||
@extend .button-base;
|
||||
|
||||
--_text-color: var(--color-base);
|
||||
--_background-color: var(--color-button-bg);
|
||||
--_accent-color: var(--color-base);
|
||||
@@ -296,8 +297,8 @@ a:not(.no-click-animation),
|
||||
color: var(--color-base);
|
||||
}
|
||||
|
||||
&:focus-visible:not(&:disabled),
|
||||
&:hover:not(&:disabled) {
|
||||
&:focus-visible:not(:disabled),
|
||||
&:hover:not(:disabled) {
|
||||
background-color: var(--color-button-bg);
|
||||
|
||||
&.btn-hover-filled,
|
||||
@@ -319,8 +320,8 @@ a:not(.no-click-animation),
|
||||
border-color: var(--color-contrast);
|
||||
}
|
||||
|
||||
&:focus-visible:not(&:disabled),
|
||||
&:hover:not(&:disabled) {
|
||||
&:focus-visible:not(:disabled),
|
||||
&:hover:not(:disabled) {
|
||||
&.btn-hover-filled,
|
||||
&.btn-hover-filled-only {
|
||||
border-color: var(--_accent-color);
|
||||
@@ -493,8 +494,10 @@ a:not(.no-click-animation),
|
||||
}
|
||||
}
|
||||
|
||||
// CARDS
|
||||
.base-card {
|
||||
/* CARDS */
|
||||
.base-card,
|
||||
.card,
|
||||
.navigation-card {
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
min-height: var(--font-size-2xl);
|
||||
@@ -517,7 +520,7 @@ a:not(.no-click-animation),
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&:where(&.warning, &.information) {
|
||||
&:where(.warning, .information) {
|
||||
padding: 1.5rem;
|
||||
line-height: 1.5;
|
||||
min-height: 0;
|
||||
@@ -529,14 +532,7 @@ a:not(.no-click-animation),
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
@extend .base-card;
|
||||
@extend .universal-body;
|
||||
}
|
||||
|
||||
.navigation-card {
|
||||
@extend .base-card;
|
||||
|
||||
padding-inline: var(--gap-xl);
|
||||
padding-block: var(--gap-md);
|
||||
|
||||
@@ -547,7 +543,7 @@ a:not(.no-click-animation),
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
// UTILITY
|
||||
/* UTILITY */
|
||||
|
||||
.wrap-as-needed {
|
||||
overflow-wrap: break-word;
|
||||
@@ -572,7 +568,7 @@ a:not(.no-click-animation),
|
||||
margin: var(--gap-sm) 0;
|
||||
}
|
||||
|
||||
// TABLE
|
||||
/* TABLE */
|
||||
.table {
|
||||
display: grid;
|
||||
grid-template-rows: repeat(auto-fill, auto);
|
||||
@@ -634,10 +630,10 @@ a:not(.no-click-animation),
|
||||
}
|
||||
}
|
||||
|
||||
// CUSTOM COMPONENTS
|
||||
// TODO: MOST OF THESE SHOULD BE MOVED TO AN OMORPHIA COMPONENT
|
||||
/* CUSTOM COMPONENTS */
|
||||
/* TODO: MOST OF THESE SHOULD BE MOVED TO AN OMORPHIA COMPONENT */
|
||||
|
||||
// TOOLTIPS
|
||||
/* TOOLTIPS */
|
||||
|
||||
.v-popper__popper.v-popper--theme-dropdown,
|
||||
.v-popper__popper.v-popper--theme-dropdown.v-popper--theme-ribbit-popout {
|
||||
@@ -690,7 +686,7 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
.v-popper__popper.v-popper__popper--hide-to .v-popper__wrapper {
|
||||
//transform: scale(.9);
|
||||
/* transform: scale(.9); */
|
||||
}
|
||||
|
||||
.v-popper__popper.v-popper--theme-tooltip {
|
||||
@@ -817,7 +813,7 @@ a:not(.no-click-animation),
|
||||
}
|
||||
}
|
||||
|
||||
// MARKDOWN
|
||||
/* MARKDOWN */
|
||||
|
||||
.markdown-body {
|
||||
h1:first-child {
|
||||
@@ -862,7 +858,8 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply mt-5 mb-3;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
h1,
|
||||
@@ -912,21 +909,25 @@ a:not(.no-click-animation),
|
||||
height: auto;
|
||||
}
|
||||
|
||||
html:not(.dark-mode, .oled-mode) & img[src$='#gh-dark-mode-only'] {
|
||||
html:not(.dark-mode, .oled-mode, .retro-mode) & img[src$='#gh-dark-mode-only'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html:is(.dark-mode, .oled-mode) & img[src$='#gh-light-mode-only'] {
|
||||
html:is(.dark-mode, .oled-mode, .retro-mode) & img[src$='#gh-light-mode-only'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
@apply bg-surface-2 rounded-xl p-4 border border-solid border-surface-5;
|
||||
background-color: var(--surface-2);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--surface-5);
|
||||
margin-top: 1rem;
|
||||
overflow-x: auto;
|
||||
|
||||
code {
|
||||
@apply bg-transparent border-0;
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
font-size: 80%;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
@@ -934,10 +935,10 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
code {
|
||||
@apply bg-surface-3 rounded-md p-4 border border-solid border-surface-5;
|
||||
padding: 0.2em 0.4em;
|
||||
font-size: 80%;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--surface-5);
|
||||
background-color: var(--color-button-bg);
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
@@ -988,19 +989,32 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
details {
|
||||
@apply border border-solid border-surface-5 bg-surface-3 rounded-xl p-2;
|
||||
border: 1px solid var(--surface-5);
|
||||
background-color: var(--surface-3);
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.5rem;
|
||||
display: grid;
|
||||
grid-template-rows: min-content 0fr;
|
||||
transition: grid-template-rows 0.3s var(--ease-out-expo);
|
||||
overflow: clip;
|
||||
|
||||
summary {
|
||||
@apply bg-surface-4 hover:bg-surface-5 p-2 flex items-center gap-1 text-contrast -m-2 border border-solid border-transparent;
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
color: var(--color-text-primary);
|
||||
margin: -0.5rem;
|
||||
border: 1px solid transparent;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
background-color: var(--color-button-bg);
|
||||
list-style: none;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-5);
|
||||
}
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
@@ -1010,7 +1024,7 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
&::before {
|
||||
@apply text-primary;
|
||||
color: var(--color-text-default);
|
||||
content: '';
|
||||
flex-shrink: 0;
|
||||
width: 1.25rem;
|
||||
@@ -1025,15 +1039,15 @@ a:not(.no-click-animation),
|
||||
}
|
||||
|
||||
> :nth-child(2) {
|
||||
@apply mt-5;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
> :nth-child(n + 2) {
|
||||
@apply mx-1;
|
||||
margin-inline: 0.25rem;
|
||||
}
|
||||
|
||||
> :last-child:not(summary) {
|
||||
@apply mb-1;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
&::details-content {
|
||||
@@ -1047,7 +1061,7 @@ a:not(.no-click-animation),
|
||||
grid-template-rows: min-content 1fr;
|
||||
|
||||
> summary {
|
||||
@apply border-b-surface-5;
|
||||
border-bottom-color: var(--surface-5);
|
||||
|
||||
&::before {
|
||||
transform: rotate(180deg);
|
||||
@@ -1094,7 +1108,7 @@ select {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: #cccccc url(http://dropdown/arrow/url/) no-repeat right center;
|
||||
background: #cccccc url('http://dropdown/arrow/url/') no-repeat right center;
|
||||
color: #000000;
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
@import 'reset';
|
||||
@import './reset.css';
|
||||
|
||||
// Use border box on everything to preserve everyone's sanity
|
||||
/* Use border box on everything to preserve everyone's sanity */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
// Defaults
|
||||
/* Defaults */
|
||||
background-color: var(--color-bg);
|
||||
color: var(--color-base);
|
||||
--font-standard:
|
||||
@@ -19,18 +19,18 @@ body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
// Font Sizes
|
||||
--font-size-xxs: 0.625rem; //10px
|
||||
--font-size-xs: 0.75rem; //12px
|
||||
--font-size-sm: 0.875rem; //14px
|
||||
--font-size-nm: 1rem; //16px
|
||||
--font-size-md: 1.125rem; //18px
|
||||
--font-size-lg: 1.25rem; //20px
|
||||
--font-size-xl: 1.5rem; //24px
|
||||
--font-size-2xl: 2rem; //32px
|
||||
--font-size-3xl: 3rem; //48px
|
||||
/* Font Sizes */
|
||||
--font-size-xxs: 0.625rem; /* 10px */
|
||||
--font-size-xs: 0.75rem; /* 12px */
|
||||
--font-size-sm: 0.875rem; /* 14px */
|
||||
--font-size-nm: 1rem; /* 16px */
|
||||
--font-size-md: 1.125rem; /* 18px */
|
||||
--font-size-lg: 1.25rem; /* 20px */
|
||||
--font-size-xl: 1.5rem; /* 24px */
|
||||
--font-size-2xl: 2rem; /* 32px */
|
||||
--font-size-3xl: 3rem; /* 48px */
|
||||
|
||||
// Font Weights
|
||||
/* Font Weights */
|
||||
--font-weight-regular: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-bold: 700;
|
||||
@@ -101,7 +101,7 @@ svg {
|
||||
transform 0.05s ease-in-out,
|
||||
outline 0.2s ease-in-out;
|
||||
|
||||
&:active:not(&:disabled) {
|
||||
&:active:not(:disabled) {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ h3 {
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
|
||||
// Scrollbar styles
|
||||
/* Scrollbar styles */
|
||||
::-webkit-scrollbar {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
@@ -149,7 +149,7 @@ h3 {
|
||||
background: var(--color-scrollbar);
|
||||
}
|
||||
|
||||
// Firefox scrollbar
|
||||
/* Firefox scrollbar */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-scrollbar) transparent;
|
||||
@@ -9,3 +9,7 @@ input[type='button'] {
|
||||
cursor: pointer;
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
|
||||
:where(*) {
|
||||
border: 0 solid currentColor;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
.light-properties {
|
||||
html,
|
||||
.light-mode,
|
||||
.light {
|
||||
--surface-1: #ebebeb;
|
||||
--surface-1-5: #ededed;
|
||||
--surface-2: #f5f5f5;
|
||||
@@ -89,7 +91,7 @@
|
||||
--color-text-default: #2c2e31;
|
||||
--color-text-tertiary: #484d54;
|
||||
|
||||
// ===
|
||||
/* === */
|
||||
|
||||
--color-bg: var(--surface-1);
|
||||
--color-raised-bg: var(--surface-3);
|
||||
@@ -188,7 +190,6 @@
|
||||
}
|
||||
|
||||
html {
|
||||
@extend .light-properties;
|
||||
--dark-color-base: #b0bac5;
|
||||
--dark-color-contrast: #ecf9fb;
|
||||
|
||||
@@ -214,22 +215,19 @@ html {
|
||||
--color-ad-highlight: var(--color-purple);
|
||||
|
||||
--color-link: var(--color-blue) !important;
|
||||
--color-link-hover: var(--color-blue) !important; // DEPRECATED, use filters in future
|
||||
--color-link-active: var(--color-blue) !important; // DEPRECATED, use filters in future
|
||||
--color-link-hover: var(--color-blue) !important; /* DEPRECATED, use filters in future */
|
||||
--color-link-active: var(--color-blue) !important; /* DEPRECATED, use filters in future */
|
||||
|
||||
--shadow-button: 0 1px 3px 0 rgba(0, 0, 0, 0.05), 0 1px 2px 0 rgba(0, 0, 0, 0.15);
|
||||
|
||||
--color-focus-ring: #ea80ff;
|
||||
}
|
||||
|
||||
.light-mode,
|
||||
.light {
|
||||
@extend .light-properties;
|
||||
}
|
||||
|
||||
.dark-mode,
|
||||
.dark,
|
||||
:root[data-theme='dark'] {
|
||||
:root[data-theme='dark'],
|
||||
.oled-mode,
|
||||
.retro-mode {
|
||||
--surface-1: #16181c;
|
||||
--surface-1-5: #1a1c20;
|
||||
--surface-2: #1d1f23;
|
||||
@@ -320,7 +318,7 @@ html {
|
||||
--color-text-default: #b0bac5;
|
||||
--color-text-tertiary: #96a2b0;
|
||||
|
||||
// ===
|
||||
/* === */
|
||||
|
||||
--color-bg: var(--surface-1);
|
||||
--color-raised-bg: var(--surface-3);
|
||||
@@ -408,7 +406,6 @@ html {
|
||||
}
|
||||
|
||||
.oled-mode {
|
||||
@extend .dark-mode;
|
||||
--surface-1: #000000;
|
||||
--surface-1-5: #050506;
|
||||
--surface-2: #09090a;
|
||||
@@ -434,7 +431,6 @@ html {
|
||||
}
|
||||
|
||||
.retro-mode {
|
||||
@extend .dark-mode;
|
||||
--surface-1: #191917;
|
||||
--surface-2: rgb(22, 22, 21);
|
||||
--surface-2-5: #3a3c3e;
|
||||
@@ -0,0 +1,2 @@
|
||||
src/locales/**
|
||||
storybook-static/**
|
||||
@@ -0,0 +1,20 @@
|
||||
# Copying
|
||||
|
||||
The source code of Modrinth's Layouts library is licensed under the GNU General Public License, Version 3 only, which is provided in the file [LICENSE](./LICENSE). However, some files listed below are licensed under a different license.
|
||||
|
||||
## Modrinth logo
|
||||
|
||||
The use of Modrinth branding elements, including but not limited to the wrench-in-labyrinth logo, the landing image, and any variations thereof, is strictly prohibited without explicit written permission from Rinth, Inc. This includes trademarks, logos, or other branding elements.
|
||||
|
||||
> All rights reserved. © 2020-2025 Rinth, Inc.
|
||||
|
||||
This includes, but may not be limited to, the following files:
|
||||
|
||||
- src/components/brand/\*
|
||||
- src/components/servers/ModrinthServersIcon.vue
|
||||
|
||||
## External logos
|
||||
|
||||
The following files are owned by their respective copyright holders and must be used within each of their Brand Guidelines:
|
||||
|
||||
- src/components/servers/MedalBackgroundImage.vue
|
||||
@@ -0,0 +1,2 @@
|
||||
import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
|
||||
export default config
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './src/locales'
|
||||
export * from './src/pages'
|
||||
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"name": "@modrinth/layouts",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"main": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
"imports": {
|
||||
"#layouts/*": "./src/*"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.ts",
|
||||
"default": "./index.ts"
|
||||
},
|
||||
"./pages": {
|
||||
"types": "./src/pages/index.ts",
|
||||
"default": "./src/pages/index.ts"
|
||||
},
|
||||
"./src/*": "./src/*"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint . && prettier --check .",
|
||||
"fix": "eslint . --fix && prettier --write .",
|
||||
"intl:extract": "formatjs extract \"src/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"src/**/*.d.ts\" --out-file src/locales/en-US/index.json --preserve-whitespace",
|
||||
"intl:prune-local": "pnpm -w scripts i18n-icu-contract prune-local --scope packages/layouts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formatjs/cli": "^6.2.12",
|
||||
"@modrinth/tooling-config": "workspace:*",
|
||||
"@storybook/addon-a11y": "^10.1.10",
|
||||
"@storybook/addon-themes": "^10.1.10",
|
||||
"@storybook/builder-vite": "^10.1.10",
|
||||
"@storybook/vue3-vite": "^10.1.10",
|
||||
"@stripe/stripe-js": "^7.3.1",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"eslint-plugin-storybook": "^10.1.10",
|
||||
"storybook": "^10.1.10",
|
||||
"stripe": "^18.1.1",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.4.6",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-component-type-helpers": "^3.1.8",
|
||||
"vue-router": "^4.6.0",
|
||||
"wrangler": "^4.65.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/commands": "^6.3.2",
|
||||
"@codemirror/lang-markdown": "^6.2.3",
|
||||
"@codemirror/language": "^6.9.3",
|
||||
"@codemirror/state": "^6.3.2",
|
||||
"@codemirror/view": "^6.22.1",
|
||||
"@intercom/messenger-js-sdk": "^0.0.14",
|
||||
"@modrinth/api-client": "workspace:*",
|
||||
"@modrinth/assets": "workspace:*",
|
||||
"@modrinth/blog": "workspace:*",
|
||||
"@modrinth/utils": "workspace:*",
|
||||
"@modrinth/ui": "workspace:*",
|
||||
"@tanstack/vue-query": "5.90.7",
|
||||
"@tresjs/cientos": "^4.3.0",
|
||||
"@tresjs/core": "^4.3.4",
|
||||
"@tresjs/post-processing": "^2.4.0",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@types/three": "^0.172.0",
|
||||
"@vintl/how-ago": "^3.0.1",
|
||||
"@vueuse/core": "^11.1.0",
|
||||
"@xterm/addon-fit": "^0.11.0",
|
||||
"@xterm/addon-search": "^0.16.0",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
"ace-builds": "^1.43.5",
|
||||
"apexcharts": "^4.0.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"dompurify": "^3.1.7",
|
||||
"es-toolkit": "^1.44.0",
|
||||
"flatpickr": "^4.6.13",
|
||||
"fabric": "^7.4.0",
|
||||
"floating-vue": "^5.2.2",
|
||||
"fuse.js": "^6.6.2",
|
||||
"highlight.js": "^11.9.0",
|
||||
"intl-messageformat": "^10.7.7",
|
||||
"jszip": "^3.10.1",
|
||||
"lru-cache": "^11.2.4",
|
||||
"markdown-it": "^13.0.2",
|
||||
"motion-v": "^2.2.1",
|
||||
"overlayscrollbars": "^2.15.1",
|
||||
"postprocessing": "^6.37.6",
|
||||
"qrcode.vue": "^3.4.1",
|
||||
"three": "^0.172.0",
|
||||
"vue-i18n": "^10.0.0",
|
||||
"vue-select": "4.0.0-beta.6",
|
||||
"vue-typed-virtual-list": "^1.0.10",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
"vue3-apexcharts": "^1.5.2",
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"web-types": "../../web-types.json"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { injectPageContext } from '@modrinth/ui'
|
||||
|
||||
const { hierarchicalSidebarAvailable } = injectPageContext()
|
||||
</script>
|
||||
<template>
|
||||
<Teleport v-if="hierarchicalSidebarAvailable" to="#sidebar">
|
||||
<aside id="page-sidebar">
|
||||
<slot />
|
||||
</aside>
|
||||
</Teleport>
|
||||
<aside v-else id="page-sidebar">
|
||||
<slot />
|
||||
</aside>
|
||||
</template>
|
||||
@@ -0,0 +1,6 @@
|
||||
<script setup lang="ts"></script>
|
||||
<template>
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { CrowdinMessages } from '@modrinth/ui'
|
||||
|
||||
export const layoutsLocaleModules = import.meta.glob<{ default: CrowdinMessages }>(
|
||||
'./locales/*/index.json',
|
||||
{ eager: false },
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as UserPage } from './user'
|
||||
@@ -0,0 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { injectModrinthClient } from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import Sidebar from '../../components/Sidebar.vue'
|
||||
import SidebarCard from '../../components/SidebarCard.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
userId: string
|
||||
}>()
|
||||
|
||||
const api = injectModrinthClient()
|
||||
const { data: user } = useQuery({
|
||||
queryKey: ['user', props.userId],
|
||||
queryFn: () => api.labrinth.users_v3.get(props.userId),
|
||||
enabled: !!props.userId,
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<img :src="user?.avatar_url" class="size-10 rounded-full" />
|
||||
<div>Hello user {{ user?.username }}!</div>
|
||||
</div>
|
||||
<Sidebar>
|
||||
<SidebarCard> Sidebar stuff!</SidebarCard>
|
||||
<SidebarCard> the stuff in the sidebar goes here</SidebarCard>
|
||||
</Sidebar>
|
||||
</template>
|
||||
@@ -0,0 +1,9 @@
|
||||
import preset from '@modrinth/tooling-config/tailwind/tailwind-preset.ts'
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
content: ['./src/**/*.{js,vue,ts,mdx}', './.storybook/**/*.{ts,js}'],
|
||||
presets: [preset],
|
||||
}
|
||||
|
||||
export default config
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'floating-vue/dist/style.css'
|
||||
import '../../assets/styles/defaults.scss'
|
||||
import '../../assets/styles/defaults.css'
|
||||
// frontend css imports
|
||||
// import '../../../apps/frontend/src/assets/styles/global.scss'
|
||||
// import '../../../apps/frontend/src/assets/styles/tailwind.css'
|
||||
|
||||
@@ -38,7 +38,7 @@ All frontend packages share a Tailwind preset at `packages/tooling-config/tailwi
|
||||
import preset from '@modrinth/tooling-config/tailwind/tailwind-preset.ts'
|
||||
```
|
||||
|
||||
CSS custom properties are defined in `packages/assets/styles/variables.scss` with light, dark, and OLED theme variants.
|
||||
CSS custom properties are defined in `packages/assets/styles/variables.css` with light, dark, and OLED theme variants.
|
||||
|
||||
### Color Usage Rules
|
||||
|
||||
@@ -61,7 +61,7 @@ CSS custom properties are defined in `packages/assets/styles/variables.scss` wit
|
||||
| `text-primary` | Default body text |
|
||||
| `text-secondary` | Reduced emphasis, secondary info |
|
||||
|
||||
**Brand and semantic colors** not all exposed as Figma variables — refer to `packages/assets/styles/variables.scss` for the full set:
|
||||
**Brand and semantic colors** not all exposed as Figma variables — refer to `packages/assets/styles/variables.css` for the full set:
|
||||
|
||||
- `bg-{color}`, `text-{color}` etc. — Primary brand colors
|
||||
- `bg-{color}-highlight` — 25% opacity semantic highlights
|
||||
|
||||
-18
@@ -111,24 +111,6 @@ function getPreviewClass(option: T): string {
|
||||
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
||||
gap: var(--gap-lg);
|
||||
|
||||
.preview {
|
||||
&.light-mode {
|
||||
@extend .light-mode;
|
||||
}
|
||||
|
||||
&.dark-mode {
|
||||
@extend .dark-mode;
|
||||
}
|
||||
|
||||
&.oled-mode {
|
||||
@extend .oled-mode;
|
||||
}
|
||||
|
||||
&.retro-mode {
|
||||
@extend .retro-mode;
|
||||
}
|
||||
}
|
||||
|
||||
.preview .example-card {
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
|
||||
Generated
+4693
-443
File diff suppressed because it is too large
Load Diff
@@ -69,8 +69,20 @@ const PRODUCT_SCOPES: Record<
|
||||
catalogScopes: ['apps/app-frontend', 'packages/ui'],
|
||||
},
|
||||
website: {
|
||||
sourceDirectories: ['apps/frontend/src', 'packages/moderation/src', 'packages/ui/src'],
|
||||
catalogScopes: ['packages/ui', 'packages/moderation', 'apps/frontend'],
|
||||
sourceDirectories: [
|
||||
'apps/frontend/src',
|
||||
// 'apps/website/src',
|
||||
'packages/layouts/src',
|
||||
'packages/moderation/src',
|
||||
'packages/ui/src',
|
||||
],
|
||||
catalogScopes: [
|
||||
'packages/ui',
|
||||
'packages/moderation',
|
||||
'packages/layouts',
|
||||
'apps/frontend',
|
||||
// 'apps/website',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -765,8 +777,10 @@ function main() {
|
||||
const scanDirs = [
|
||||
'apps/frontend/src',
|
||||
'apps/app-frontend/src',
|
||||
// 'apps/website/src',
|
||||
'packages/ui/src',
|
||||
'packages/moderation/src',
|
||||
'packages/layouts/src',
|
||||
]
|
||||
|
||||
if (!jsonOutput && !quiet) {
|
||||
|
||||
@@ -85,6 +85,8 @@
|
||||
"apps/frontend/src/locales/**/*.json",
|
||||
"packages/moderation/src/**/*.vue",
|
||||
"packages/moderation/src/locales/**/*.json",
|
||||
"packages/layouts/src/**/*.vue",
|
||||
"packages/layouts/src/locales/**/*.json",
|
||||
"packages/ui/src/**/*.vue",
|
||||
"packages/ui/src/locales/**/*.json"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user