diff --git a/.gitignore b/.gitignore index 4b21ab0..fbd17f3 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,9 @@ __pycache__/ # Approved, versioned brand resources are package source assets. !packages/brand/assets/**/*.png !packages/brand/docs/logo-preview.png +/apps/studio/public/brand/ +/apps/studio/public/favicon.ico +/apps/studio/public/apple-touch-icon.png +/apps/waterfall-wiki/public/brand/ +/apps/waterfall-wiki/public/favicon.ico +/apps/waterfall-wiki/public/apple-touch-icon.png diff --git a/Dockerfile b/Dockerfile index 67928ef..f081c17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,14 +7,15 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* FROM base AS dependencies +WORKDIR /repo/apps/waterfall-wiki LABEL io.entroia.wiki.build="true" RUN corepack enable && corepack prepare pnpm@11.25.0 --activate COPY apps/waterfall-wiki/pnpm-lock.yaml ./ -COPY pnpm-workspace.yaml /tmp/monorepo-policy.yaml -RUN node -e "const fs=require('fs');const text=fs.readFileSync('/tmp/monorepo-policy.yaml','utf8');fs.writeFileSync('pnpm-workspace.yaml', text.slice(text.indexOf('allowBuilds:')));" -RUN pnpm fetch --frozen-lockfile --fetch-timeout=300000 --network-concurrency=8 +COPY pnpm-workspace.yaml /repo/pnpm-workspace.yaml +COPY packages/brand/ /repo/packages/brand/ +RUN pnpm --ignore-workspace fetch --frozen-lockfile --fetch-timeout=300000 --network-concurrency=8 COPY apps/waterfall-wiki/package.json ./ -RUN pnpm install --offline --frozen-lockfile +RUN pnpm --filter @prompt/waterfall-wiki install --offline --frozen-lockfile FROM dependencies AS build # .dockerignore excludes docs and operational notes without extra legacy COPY snapshots. @@ -28,9 +29,9 @@ CMD ["npm", "run", "test:integration"] FROM base AS runtime ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 \ FFMPEG_PATH=/usr/bin/ffmpeg FFPROBE_PATH=/usr/bin/ffprobe -COPY --from=build --chown=node:node /app/.next/standalone/ ./ -COPY --from=build --chown=node:node /app/dist/worker.cjs /app/dist/bootstrap.cjs /app/dist/publish-learning-series.cjs /app/dist/auth-cli.cjs ./ -COPY --from=build --chown=node:node /app/db/ ./db/ +COPY --from=build --chown=node:node /repo/apps/waterfall-wiki/.next/standalone/ ./ +COPY --from=build --chown=node:node /repo/apps/waterfall-wiki/dist/worker.cjs /repo/apps/waterfall-wiki/dist/bootstrap.cjs /repo/apps/waterfall-wiki/dist/publish-learning-series.cjs /repo/apps/waterfall-wiki/dist/auth-cli.cjs ./ +COPY --from=build --chown=node:node /repo/apps/waterfall-wiki/db/ ./db/ COPY --chown=node:node apps/waterfall-wiki/scripts/container-health.mjs ./ COPY --chown=node:node apps/waterfall-wiki/scripts/import-character-packs.mjs apps/waterfall-wiki/scripts/verify-character-pack.mjs ./scripts/ COPY --chown=node:node apps/waterfall-wiki/seed/characters/ ./seed/characters/ diff --git a/apps/studio/Dockerfile b/apps/studio/Dockerfile index e05abfa..8338c32 100644 --- a/apps/studio/Dockerfile +++ b/apps/studio/Dockerfile @@ -1,23 +1,24 @@ FROM node:24-bookworm-slim AS build -WORKDIR /app +WORKDIR /repo/apps/studio RUN corepack enable && corepack prepare pnpm@11.25.0 --activate COPY apps/studio/pnpm-lock.yaml ./ -COPY pnpm-workspace.yaml /tmp/monorepo-policy.yaml -RUN node -e "const fs=require('fs');const text=fs.readFileSync('/tmp/monorepo-policy.yaml','utf8');fs.writeFileSync('pnpm-workspace.yaml', text.slice(text.indexOf('allowBuilds:')));" -RUN pnpm fetch --frozen-lockfile --fetch-timeout=300000 --network-concurrency=8 +COPY pnpm-workspace.yaml /repo/pnpm-workspace.yaml +COPY packages/brand/ /repo/packages/brand/ +RUN pnpm --ignore-workspace fetch --frozen-lockfile --fetch-timeout=300000 --network-concurrency=8 COPY apps/studio/package.json ./ -RUN pnpm install --offline --frozen-lockfile +RUN pnpm --filter @prompt/studio install --offline --frozen-lockfile COPY apps/studio/ . # Compare the two public parameter validators inside the isolated CI build. -COPY apps/waterfall-wiki/src/lib/layout-parameters.ts /waterfall-wiki/src/lib/layout-parameters.ts -COPY apps/waterfall-wiki/src/lib/series.ts /waterfall-wiki/src/lib/series.ts -COPY apps/waterfall-wiki/src/lib/canvas-document.ts /waterfall-wiki/src/lib/canvas-document.ts +COPY apps/waterfall-wiki/src/lib/layout-parameters.ts /repo/apps/waterfall-wiki/src/lib/layout-parameters.ts +COPY apps/waterfall-wiki/src/lib/series.ts /repo/apps/waterfall-wiki/src/lib/series.ts +COPY apps/waterfall-wiki/src/lib/canvas-document.ts /repo/apps/waterfall-wiki/src/lib/canvas-document.ts RUN pnpm typecheck && pnpm test && pnpm build && pnpm test:smoke FROM node:24-bookworm-slim WORKDIR /app ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 -COPY --from=build --chown=node:node /app/.next/standalone/ ./ -COPY --from=build --chown=node:node /app/.next/static/ ./.next/static/ +COPY --from=build --chown=node:node /repo/apps/studio/.next/standalone/ ./ +COPY --from=build --chown=node:node /repo/apps/studio/.next/static/ ./.next/static/ +COPY --from=build --chown=node:node /repo/apps/studio/public/ ./public/ USER node EXPOSE 3000 CMD ["node", "server.js"] diff --git a/apps/studio/package.json b/apps/studio/package.json index e8cc3c3..0b75aab 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -2,18 +2,20 @@ "name": "@prompt/studio", "private": true, "scripts": { - "dev": "next dev -p 3001", - "build": "next build", + "dev": "pnpm brand:prepare && next dev -p 3001", + "build": "pnpm brand:prepare && next build", "start": "next start", "typecheck": "next typegen && tsc --noEmit", "test": "node --test tests/*.test.mjs", - "test:smoke": "node scripts/smoke.mjs" + "test:smoke": "node scripts/smoke.mjs", + "brand:prepare": "node ../../packages/brand/scripts/prepare-app.mjs" }, "dependencies": { "next": "16.4.2", "react": "19.3.1", "react-dom": "19.3.1", - "lucide-react": "1.61.0" + "lucide-react": "1.61.0", + "@endoleap/brand": "workspace:*" }, "devDependencies": { "@tailwindcss/postcss": "4.3.3", diff --git a/apps/studio/pnpm-lock.yaml b/apps/studio/pnpm-lock.yaml index 5def37e..d65df4b 100644 --- a/apps/studio/pnpm-lock.yaml +++ b/apps/studio/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@endoleap/brand': + specifier: workspace:* + version: link:../../packages/brand lucide-react: specifier: 1.61.0 version: 1.61.0(@types/react@19.3.0)(react@19.3.1) diff --git a/apps/studio/src/components/Brand.tsx b/apps/studio/src/components/Brand.tsx new file mode 100644 index 0000000..8a55954 --- /dev/null +++ b/apps/studio/src/components/Brand.tsx @@ -0,0 +1,4 @@ +/** The approved mark is copied from @endoleap/brand during the remote build. */ +export function Brand({ compact = false }: { compact?: boolean }) { + return 啡跃{!compact && Endoleap}; +} diff --git a/apps/studio/src/components/LayoutSelection.tsx b/apps/studio/src/components/LayoutSelection.tsx index 144bf27..9683bb0 100644 --- a/apps/studio/src/components/LayoutSelection.tsx +++ b/apps/studio/src/components/LayoutSelection.tsx @@ -10,5 +10,5 @@ export function LayoutSelection(){ async function download(format:'svg'|'json'){ try{setStatus('正在生成…');const r=await fetch('/studio/api/export/layout-selection?format='+format,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({layoutId:layout.id,...current})});if(!r.ok)throw Error();const url=URL.createObjectURL(await r.blob()),a=document.createElement('a');a.href=url;a.download=layout.id+'.'+format;a.click();setTimeout(()=>URL.revokeObjectURL(url),500);setStatus('已导出当前模板。')}catch{setStatus('导出失败,请重试。')} } - return
三种排版 · Studio 工具
← PROMPT 使用教程STUDIO / LAYOUT SELECTION
REF-01 / REF-07 / REF-26

三个构图,各有位置。

切换真实原图对应的模板,分别试文字与配色。图位与装饰按教程构件重建为干净矢量;当前只放占位内容。