@xiaobuyu/nodesign 0.0.1
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.
- package/LICENSE +661 -0
- package/README.md +140 -0
- package/bin/nodesign.js +176 -0
- package/package.json +104 -0
- package/server/api/README.md +45 -0
- package/server/api/_guard.js +75 -0
- package/server/api/admin.js +187 -0
- package/server/api/assets/docx-page.js +103 -0
- package/server/api/assets/helpers.js +22 -0
- package/server/api/assets/notes.js +144 -0
- package/server/api/assets.js +896 -0
- package/server/api/board.js +57 -0
- package/server/api/browse.js +138 -0
- package/server/api/canvas.js +444 -0
- package/server/api/chatai.js +324 -0
- package/server/api/exports/build-standalone.js +980 -0
- package/server/api/exports/cards.js +118 -0
- package/server/api/exports/docx-pdf.js +46 -0
- package/server/api/exports/export-page.js +142 -0
- package/server/api/exports/handoff.js +147 -0
- package/server/api/exports.js +690 -0
- package/server/api/instruction.js +75 -0
- package/server/api/local.js +115 -0
- package/server/api/me.js +116 -0
- package/server/api/memory.js +185 -0
- package/server/api/pending-changes.js +366 -0
- package/server/api/plugins.js +164 -0
- package/server/api/projects.js +220 -0
- package/server/api/publish.js +64 -0
- package/server/api/recent.js +73 -0
- package/server/api/sessions.js +589 -0
- package/server/api/skills.js +77 -0
- package/server/api/standalone-fit.js +168 -0
- package/server/api/turn-compose.js +180 -0
- package/server/api/turn-inflight.js +44 -0
- package/server/api/turn.js +669 -0
- package/server/auth/README.md +17 -0
- package/server/auth/middleware.js +138 -0
- package/server/auth/origin-guard.js +71 -0
- package/server/auth/session.js +108 -0
- package/server/auth/tier.js +113 -0
- package/server/auth/users-store.js +348 -0
- package/server/edit/README.md +29 -0
- package/server/engine/README.md +113 -0
- package/server/engine/agent/agent-shared.js +550 -0
- package/server/engine/agent/auto-mode-default-hard-deny.txt +4 -0
- package/server/engine/agent/auto-mode-rules.js +78 -0
- package/server/engine/agent/context.js +418 -0
- package/server/engine/agent/events.js +464 -0
- package/server/engine/agent/hooks/canvas-validate.js +199 -0
- package/server/engine/agent/hooks/failure.js +120 -0
- package/server/engine/agent/hooks/file-events.js +75 -0
- package/server/engine/agent/hooks/lifecycle.js +233 -0
- package/server/engine/agent/hooks/post-canvas-focus.js +80 -0
- package/server/engine/agent/hooks/post-guidance.js +206 -0
- package/server/engine/agent/hooks/post-subagent-report.js +104 -0
- package/server/engine/agent/hooks/post-trim.js +58 -0
- package/server/engine/agent/hooks/pre-board-neighborhood.js +34 -0
- package/server/engine/agent/hooks/pre-defaults.js +84 -0
- package/server/engine/agent/hooks/pre-injectors.js +277 -0
- package/server/engine/agent/hooks/pre-performance-log-guard.js +78 -0
- package/server/engine/agent/hooks/pre-starter-files.js +61 -0
- package/server/engine/agent/hooks/pre-workspace-scope-guard.js +78 -0
- package/server/engine/agent/hooks/site-validate.js +94 -0
- package/server/engine/agent/hooks/tool-prompts.js +31 -0
- package/server/engine/agent/hooks/turn-state-memory.js +56 -0
- package/server/engine/agent/hooks/user-prompt-submit.js +215 -0
- package/server/engine/agent/hooks.js +354 -0
- package/server/engine/agent/init-contract.js +69 -0
- package/server/engine/agent/isolation.js +159 -0
- package/server/engine/agent/model-context.js +359 -0
- package/server/engine/agent/model-table.js +292 -0
- package/server/engine/agent/plugin-loader.js +266 -0
- package/server/engine/agent/prompts/nodesign-prelude.md +336 -0
- package/server/engine/agent/prompts/tools/ask-user-question-protocol.md +71 -0
- package/server/engine/agent/prompts/tools/direct-edit-protocol.md +98 -0
- package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +583 -0
- package/server/engine/agent/prompts/tools/generate-image-cookbook.md +483 -0
- package/server/engine/agent/prompts/tools/hybrid-reference.md +100 -0
- package/server/engine/agent/prompts/tools/paint-still-cookbook.md +270 -0
- package/server/engine/agent/prompts/tools/roll-film-cookbook.md +70 -0
- package/server/engine/agent/prompts/tools/site-reference.md +106 -0
- package/server/engine/agent/prompts/tools/tweaks-syntax.md +125 -0
- package/server/engine/agent/prompts/tools/vision-checker-dispatch.md +48 -0
- package/server/engine/agent/session-loop.js +1024 -0
- package/server/engine/agent/session-model.js +164 -0
- package/server/engine/agent/skill.js +204 -0
- package/server/engine/agent/system-prompts.js +86 -0
- package/server/engine/agent/task-events.js +78 -0
- package/server/engine/agents/ds-extractor.md +132 -0
- package/server/engine/agents/explorer.md +190 -0
- package/server/engine/agents/index.js +230 -0
- package/server/engine/agents/schemas/design-system.json +156 -0
- package/server/engine/agents/schemas/tweak-schema.json +113 -0
- package/server/engine/agents/tweak-proposer.md +127 -0
- package/server/engine/agents/vision-checker.md +254 -0
- package/server/engine/browse/capture.js +422 -0
- package/server/engine/browse/card.js +137 -0
- package/server/engine/browse/handover.js +59 -0
- package/server/engine/browse/page-digest.js +119 -0
- package/server/engine/browse/refs.js +196 -0
- package/server/engine/browse/registry.js +307 -0
- package/server/engine/browse/screencast.js +170 -0
- package/server/engine/browse/state.js +121 -0
- package/server/engine/chatai/chat-log.js +79 -0
- package/server/engine/chatai/index.js +193 -0
- package/server/engine/chatai/openai-compat.js +152 -0
- package/server/engine/chatai/orchestrate.js +309 -0
- package/server/engine/chatai/perform.js +40 -0
- package/server/engine/chatai/summarize.js +79 -0
- package/server/engine/mcp/capability-gate.js +52 -0
- package/server/engine/mcp/index.js +339 -0
- package/server/engine/mcp/param-sanitizer.js +142 -0
- package/server/engine/mcp/tools/arrange-on-board.js +124 -0
- package/server/engine/mcp/tools/artifact-session.js +278 -0
- package/server/engine/mcp/tools/browse-computer.js +421 -0
- package/server/engine/mcp/tools/browse-find-batch.js +183 -0
- package/server/engine/mcp/tools/browse-screenshot.js +157 -0
- package/server/engine/mcp/tools/browse.js +480 -0
- package/server/engine/mcp/tools/build-docx.js +101 -0
- package/server/engine/mcp/tools/clear-pending-changes.js +99 -0
- package/server/engine/mcp/tools/create-on-board.js +155 -0
- package/server/engine/mcp/tools/crystallize-skill.js +168 -0
- package/server/engine/mcp/tools/deliver-files.js +0 -0
- package/server/engine/mcp/tools/explain-style.js +237 -0
- package/server/engine/mcp/tools/export-handoff.js +133 -0
- package/server/engine/mcp/tools/expose-tweaks.js +149 -0
- package/server/engine/mcp/tools/generate-image.js +842 -0
- package/server/engine/mcp/tools/get-computed-styles.js +164 -0
- package/server/engine/mcp/tools/get-pending-changes.js +205 -0
- package/server/engine/mcp/tools/h3box-ssh.js +84 -0
- package/server/engine/mcp/tools/helpers/acquire-page.js +82 -0
- package/server/engine/mcp/tools/helpers/motion-lab.js +554 -0
- package/server/engine/mcp/tools/helpers/motion-scroll.js +112 -0
- package/server/engine/mcp/tools/helpers/perception-page.js +215 -0
- package/server/engine/mcp/tools/helpers/reference-download.js +103 -0
- package/server/engine/mcp/tools/helpers/rembg-bridge.py +80 -0
- package/server/engine/mcp/tools/helpers/rembg.js +273 -0
- package/server/engine/mcp/tools/helpers/shot-pipeline.js +280 -0
- package/server/engine/mcp/tools/highlight.js +68 -0
- package/server/engine/mcp/tools/list-pages.js +222 -0
- package/server/engine/mcp/tools/lookup-tags.js +59 -0
- package/server/engine/mcp/tools/navigate-to-page.js +60 -0
- package/server/engine/mcp/tools/organize-board.js +64 -0
- package/server/engine/mcp/tools/paint-still.js +434 -0
- package/server/engine/mcp/tools/pin-to-board.js +130 -0
- package/server/engine/mcp/tools/preview-deck.js +130 -0
- package/server/engine/mcp/tools/profile-scroll.js +305 -0
- package/server/engine/mcp/tools/publish-site.js +102 -0
- package/server/engine/mcp/tools/query-elements.js +195 -0
- package/server/engine/mcp/tools/read-board.js +103 -0
- package/server/engine/mcp/tools/read-document.js +93 -0
- package/server/engine/mcp/tools/read-page.js +264 -0
- package/server/engine/mcp/tools/read-tavern-json.js +143 -0
- package/server/engine/mcp/tools/record-decision.js +140 -0
- package/server/engine/mcp/tools/relate-on-board.js +110 -0
- package/server/engine/mcp/tools/remove-background.js +391 -0
- package/server/engine/mcp/tools/report-issue.js +115 -0
- package/server/engine/mcp/tools/roll-film.js +266 -0
- package/server/engine/mcp/tools/screenshot-docx.js +138 -0
- package/server/engine/mcp/tools/screenshot-url.js +195 -0
- package/server/engine/mcp/tools/screenshot.js +583 -0
- package/server/engine/mcp/tools/tier-gate.js +96 -0
- package/server/engine/mcp/tools/trace-motion.js +215 -0
- package/server/engine/mcp/tools/web-search.js +548 -0
- package/server/engine/motion/inventory.js +349 -0
- package/server/engine/perception/session.js +235 -0
- package/server/engine/plugins/nodesign/.claude-plugin/plugin.json +5 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +192 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/canvas.template.html +667 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/hybrid-grid.md +22 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/image-led-cover.md +25 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/portrait.md +23 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/quote-backdrop.md +21 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/section-divider.md +23 -0
- package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/text-led.md +21 -0
- package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +162 -0
- package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +407 -0
- package/server/engine/plugins/nodesign/skills/docx-craft//346/226/207/346/241/243.template.json +80 -0
- package/server/engine/plugins/nodesign/skills/rp-craft/SKILL.md +228 -0
- package/server/engine/plugins/nodesign/skills/rp-craft/patterns//346/274/224/345/207/272/351/241/265-/346/234/200/345/260/217/345/256/236/347/216/260.html +78 -0
- package/server/engine/plugins/nodesign/skills/rp-craft//346/274/224/345/207/272.template.js +268 -0
- package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +323 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/build-lane.md +134 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/cutout-collage.md +61 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/mock-app.md +163 -0
- package/server/engine/plugins/nodesign/skills/site-craft/patterns/page-transitions.md +86 -0
- package/server/engine/runs/active-runs.js +698 -0
- package/server/engine/runs/live-turn.js +252 -0
- package/server/engine/runs/store.js +364 -0
- package/server/engine/runs/turn-relay.js +217 -0
- package/server/engine/runtime/workspace.js +164 -0
- package/server/index.js +235 -0
- package/server/lib/artifact-file-path.js +80 -0
- package/server/lib/artifact-target.js +284 -0
- package/server/lib/asset-refs.js +239 -0
- package/server/lib/async-queue.js +104 -0
- package/server/lib/auto-relations.js +130 -0
- package/server/lib/binding-types.js +60 -0
- package/server/lib/board-kind-sizes.js +62 -0
- package/server/lib/board-relations.js +133 -0
- package/server/lib/browse-proxy.js +180 -0
- package/server/lib/canvas-id.js +36 -0
- package/server/lib/cover.js +227 -0
- package/server/lib/danbooru-tags.js +291 -0
- package/server/lib/doc-extract.js +156 -0
- package/server/lib/docx/build-from-source.js +260 -0
- package/server/lib/docx/build.js +490 -0
- package/server/lib/docx/dump-styles.js +287 -0
- package/server/lib/docx/fonts/nodesign-cjk.conf +164 -0
- package/server/lib/docx/merge-runs.js +129 -0
- package/server/lib/docx/numbering.js +218 -0
- package/server/lib/docx/order.js +152 -0
- package/server/lib/docx/rawzip.js +172 -0
- package/server/lib/docx/render.js +92 -0
- package/server/lib/docx/text-lint.js +225 -0
- package/server/lib/docx/tokens.js +335 -0
- package/server/lib/docx/units.js +29 -0
- package/server/lib/docx/xml.js +291 -0
- package/server/lib/docx-pages.js +187 -0
- package/server/lib/export-collect.js +289 -0
- package/server/lib/export-package.js +210 -0
- package/server/lib/html-srcset.js +145 -0
- package/server/lib/image-variant.js +460 -0
- package/server/lib/ingress/forward-openai-chat.js +305 -0
- package/server/lib/ingress/openai-chat.js +491 -0
- package/server/lib/ingress/session-notice.js +66 -0
- package/server/lib/ingress/session-routes.js +68 -0
- package/server/lib/ingress/slot-probe.js +130 -0
- package/server/lib/ingress/upstream-billing.js +52 -0
- package/server/lib/ingress/upstream-fail-streak.js +72 -0
- package/server/lib/ingress/upstream-truncation.js +48 -0
- package/server/lib/issues-store.js +182 -0
- package/server/lib/kinds/deck.js +72 -0
- package/server/lib/kinds/docx.js +283 -0
- package/server/lib/kinds/file-kinds.js +113 -0
- package/server/lib/kinds/index.js +202 -0
- package/server/lib/kinds/site.js +161 -0
- package/server/lib/model-ingress.js +543 -0
- package/server/lib/moderation.js +255 -0
- package/server/lib/notice-store.js +103 -0
- package/server/lib/plugin-install.js +104 -0
- package/server/lib/plugin-validator.js +721 -0
- package/server/lib/publish-store.js +115 -0
- package/server/lib/quick-summary.js +52 -0
- package/server/lib/quota.js +270 -0
- package/server/lib/rate-window.js +29 -0
- package/server/lib/reference-assets.js +92 -0
- package/server/lib/region-shot.js +135 -0
- package/server/lib/safe-path.js +73 -0
- package/server/lib/sdk-session.js +33 -0
- package/server/lib/showcase-store.js +92 -0
- package/server/lib/site-publish.js +465 -0
- package/server/lib/ssrf-guard.js +432 -0
- package/server/lib/task-scan.js +158 -0
- package/server/lib/tavern-json.js +154 -0
- package/server/lib/video-variant.js +237 -0
- package/server/lib/workspace-path.js +33 -0
- package/server/ops/fix-sdk-musl.mjs +40 -0
- package/server/ops/install-macos-fonts.sh +114 -0
- package/server/ops/macos-fonts.conf +336 -0
- package/server/ops/sandbox-shim/bwrap +57 -0
- package/server/projects/assets-summary.js +119 -0
- package/server/projects/auto-name.js +53 -0
- package/server/projects/board-store.js +640 -0
- package/server/projects/move-entry.js +103 -0
- package/server/projects/store.js +270 -0
- package/server/projects/ui-config.js +54 -0
- package/server/projects/workspace-templates.js +53 -0
- package/server/projects/workspace.js +1025 -0
- package/server/runtime/capabilities.js +153 -0
- package/server/runtime/local-config.js +177 -0
- package/server/runtime/local-env.js +88 -0
- package/server/runtime/platform.js +342 -0
- package/server/runtime/profile.js +72 -0
- package/server/services/rembg-launcher.js +313 -0
- package/server/services/rembg-service.py +334 -0
- package/server/shared/README.md +25 -0
- package/server/shared/deck.js +54 -0
- package/server/shared/time.js +49 -0
- package/server/style-pipeline/README.md +53 -0
- package/server/ws/broker.js +36 -0
- package/server/ws/browse-channel.js +177 -0
- package/server/ws/index.js +386 -0
- package/web/README.md +89 -0
- package/web/dist/assets/BrowserWindow-Dc7J7CYc.js +11 -0
- package/web/dist/assets/DeckWindow-4G0xX7P3.js +16 -0
- package/web/dist/assets/DocxWindow-BXQsoPkh.js +16 -0
- package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/web/dist/assets/SiteWindow-D6eS-2gM.js +18 -0
- package/web/dist/assets/again-D8tfgKKO.webp +0 -0
- package/web/dist/assets/caveat-nd-CP6HlsNg.woff2 +0 -0
- package/web/dist/assets/clock-xJhvfYpS.webp +0 -0
- package/web/dist/assets/film-cut-BBKMwH7q.webp +0 -0
- package/web/dist/assets/film-still-BZ_DL9Tt.webp +0 -0
- package/web/dist/assets/index-C0KUf6Wd.css +1 -0
- package/web/dist/assets/index-Cbl3ATvp.js +2125 -0
- package/web/dist/assets/ink-desk-BRbxeDsR.webp +0 -0
- package/web/dist/assets/ink-night-Bz4BT3XH.webp +0 -0
- package/web/dist/assets/ink-portrait-C0DM4V8Q.webp +0 -0
- package/web/dist/assets/longcang-regular-C0uvTuKa.woff2 +0 -0
- package/web/dist/assets/lxgw-nd-bold-DbRfiTgo.woff2 +0 -0
- package/web/dist/assets/lxgw-nd-regular-CpMw9Ehg.woff2 +0 -0
- package/web/dist/assets/pending-edit-apply-DTjo2geW.js +31 -0
- package/web/dist/assets/question-8H4HSqxh.webp +0 -0
- package/web/dist/assets/reject-BaPJqElj.webp +0 -0
- package/web/dist/assets/rotate-cw-LMT3x1Zj.js +11 -0
- package/web/dist/assets/rp-portrait-CbrGpew2.webp +0 -0
- package/web/dist/assets/rp-street-C4jVKjxx.webp +0 -0
- package/web/dist/assets/square-dashed-mouse-pointer-CBoAkfhi.js +11 -0
- package/web/dist/assets/tangle-DIxHVNuT.webp +0 -0
- package/web/dist/assets/thisone-BylZKglV.webp +0 -0
- package/web/dist/assets/thumb-DO1wfK1I.webp +0 -0
- package/web/dist/index.html +18 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# 应用道 —— 用模拟数据真跑起来的站点
|
|
2
|
+
|
|
3
|
+
站点道做的是「读的东西」(作品集、博客、落地页)。这份配方讲另一种:**用户能在里面
|
|
4
|
+
做事**的站 —— 登录、提交、筛选、收藏、管理。数据全是假的,但它得**真的在跑**。
|
|
5
|
+
|
|
6
|
+
平台的定位在这里要说清楚:**我们做设计和交接,不做托管运行**。你交出去的是一个能演示、
|
|
7
|
+
能被接手的完整前端 + 一份「后端要实现什么」的清单。真数据和服务器是用户自己的事。
|
|
8
|
+
|
|
9
|
+
## 什么时候进这条道
|
|
10
|
+
|
|
11
|
+
**真信号**(有一条就是):
|
|
12
|
+
- 用户的描述里有「用户能……」:登录、下单、报名、筛选、收藏、评论、管理
|
|
13
|
+
- 出现了角色分工:访客 / 会员 / 管理员看到的东西不一样
|
|
14
|
+
- 出现了数据实体:订单、文章、成员、商品、日程 —— 这些东西有列表、有详情、会增删
|
|
15
|
+
|
|
16
|
+
**假信号**(别为它上应用道):
|
|
17
|
+
- 只是页面多 —— 那是多页站点
|
|
18
|
+
- 只要一个联系表单 —— 静态表单服务或 mailto 就够
|
|
19
|
+
- 只是想显得功能丰富 —— 加一堆点不动的按钮比没有更糟
|
|
20
|
+
|
|
21
|
+
## 铁律:数据只从一个地方来
|
|
22
|
+
|
|
23
|
+
**页面永远不许直接碰假数据。** 所有读写走 `api/` 这一层函数。
|
|
24
|
+
|
|
25
|
+
这不是洁癖,它决定了「交给用户自己接」是不是一句空话:假数据散在页面里,用户换真后端
|
|
26
|
+
等于重写整个前端;收在一层里,他只改一个目录。
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
<站名>/
|
|
30
|
+
index.html 列表.html 详情.html 后台.html
|
|
31
|
+
app/
|
|
32
|
+
api.js ← 唯一出口,页面只从这里拿数据
|
|
33
|
+
mock.js ← 假实现:种子 + localStorage
|
|
34
|
+
seed.js ← 种子数据
|
|
35
|
+
style.css
|
|
36
|
+
README.md ← 交接说明,见最后一节
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**`api.js` 的每个函数签名,就是用户未来后端的接口清单。** 所以它必须长得像真的在调网络:
|
|
40
|
+
`async`、返回 Promise、失败会 throw。
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
// app/api.js —— 页面只认这一层。换真后端时,只有这个文件要改。
|
|
44
|
+
import * as impl from './mock.js';
|
|
45
|
+
|
|
46
|
+
export const listPosts = (q) => impl.listPosts(q); // GET /api/posts
|
|
47
|
+
export const getPost = (id) => impl.getPost(id); // GET /api/posts/:id
|
|
48
|
+
export const createPost = (draft) => impl.createPost(draft); // POST /api/posts
|
|
49
|
+
export const login = (u, p) => impl.login(u, p); // POST /api/auth/login
|
|
50
|
+
export const me = () => impl.me(); // GET /api/me
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
右边那列注释别省 —— 它就是交接文档的草稿,README 里的接口清单直接从这儿抄。
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
// app/mock.js —— 假实现。真接后端时整份删掉,把 api.js 换成 fetch。
|
|
57
|
+
import { SEED } from './seed.js';
|
|
58
|
+
|
|
59
|
+
// ⚠️ key 必须带站名前缀。预览时所有任务同源(都挂在 /api/projects/<pid>/artifact-file/
|
|
60
|
+
// 下面),两个 mock 站用同一个 'posts' 会串数据;发布之后各自独立域名又不串了 ——
|
|
61
|
+
// 「预览里坏、线上好」这种 bug 最难查,一开始就把前缀写死。
|
|
62
|
+
// (2026-08-18 起自检走 http,origin 跟用户预览一致,localStorage 真的能读写了;
|
|
63
|
+
// 在那之前走 file://,origin 是字符串 "null",你看到的和用户看到的不是一回事。
|
|
64
|
+
// ⚠️ 但**别指望自检能替你验出"串数据"和"刷新还在"**:每次感知调用都是一只
|
|
65
|
+
// 全新的浏览器、只开一个任务的一个页面,localStorage 每次都是空的。这两条
|
|
66
|
+
// 只有用户在自己浏览器里连着点才看得出来 —— 所以前缀要一开始就写死,
|
|
67
|
+
// 不是"等看到问题再加"。)
|
|
68
|
+
const NS = 'demo:蘑菇书店:';
|
|
69
|
+
const read = (k, fb) => { try { return JSON.parse(localStorage.getItem(NS + k)) ?? fb; } catch { return fb; } };
|
|
70
|
+
const write = (k, v) => localStorage.setItem(NS + k, JSON.stringify(v));
|
|
71
|
+
|
|
72
|
+
// 假的也要有网络的手感:没有延迟就永远看不见加载态,等于没做加载态。
|
|
73
|
+
const wait = () => new Promise(r => setTimeout(r, 120 + Math.random() * 280));
|
|
74
|
+
|
|
75
|
+
export async function listPosts(q = {}) {
|
|
76
|
+
await wait();
|
|
77
|
+
let rows = read('posts', SEED.posts);
|
|
78
|
+
if (q.keyword) rows = rows.filter(p => p.title.includes(q.keyword));
|
|
79
|
+
if (q.tag) rows = rows.filter(p => p.tags.includes(q.tag));
|
|
80
|
+
return rows;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function createPost(draft) {
|
|
84
|
+
await wait();
|
|
85
|
+
if (!draft.title?.trim()) throw new Error('标题不能为空'); // 失败路径要真的存在
|
|
86
|
+
const rows = read('posts', SEED.posts);
|
|
87
|
+
const row = { ...draft, id: `p_${Date.now().toString(36)}`, createdAt: new Date().toISOString() };
|
|
88
|
+
write('posts', [row, ...rows]); // 写了要落盘,刷新还在
|
|
89
|
+
return row;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 「跑起来」的硬定义
|
|
94
|
+
|
|
95
|
+
做到下面五条才叫跑起来,缺一条就还是个点不动的样子货:
|
|
96
|
+
|
|
97
|
+
1. **四态齐全**:加载中 / 空 / 出错 / 有数据。只写 happy path 的页面,一遇到真数据就散架
|
|
98
|
+
2. **写操作刷新后还在**(localStorage)。这是「在跑」和「死页面」的分水岭,用户会第一个试它。
|
|
99
|
+
⚠️ 这一条**你自己验不了**(每次感知调用都是全新浏览器,没有"上一次")——
|
|
100
|
+
代码上保证它:写走 `write()`、读走 `read()`、别把状态只放在内存变量里,
|
|
101
|
+
然后在交付话术里请用户点一下试试
|
|
102
|
+
3. **失败路径真的能触发**:留一个进得去的错误入口(提交空标题、搜一个没有的词),
|
|
103
|
+
别让错误态成为一段永远执行不到的代码
|
|
104
|
+
4. **筛选 / 排序 / 分页真的作用在数据上**,不是摆三个按钮改改样式
|
|
105
|
+
5. **表单有校验**,且校验失败的样子是设计过的
|
|
106
|
+
|
|
107
|
+
## 种子数据要像真的
|
|
108
|
+
|
|
109
|
+
假数据最容易露馅的地方不是功能,是内容:张三李四、item 1 / 2 / 3、Lorem ipsum、
|
|
110
|
+
所有头像同一张、日期全是同一天。这些东西一眼就把「演示」写在脸上。
|
|
111
|
+
|
|
112
|
+
- 名字、标题、正文、数量级、时间分布,都按真实场景写
|
|
113
|
+
- **必须掺边界样本**:超长标题、空列表、缺图、错误项、极端数值、只有一条的列表
|
|
114
|
+
|
|
115
|
+
边界样本一箭双雕:既是版面验收(撑不撑得住),又是交接价值 —— 接手的人一眼就看到
|
|
116
|
+
这套 UI 的边界在哪。**只有漂亮数据的 demo 是在骗自己。**
|
|
117
|
+
|
|
118
|
+
## 假登录
|
|
119
|
+
|
|
120
|
+
- **不许收真凭据。** 输入框旁边直说这是演示
|
|
121
|
+
- 演示账号密码直接印在页面上(`admin / demo`),别让人猜
|
|
122
|
+
- 登录态就是 localStorage 里一个标记,别假装有 token 体系
|
|
123
|
+
|
|
124
|
+
## 页面形态:多页优先
|
|
125
|
+
|
|
126
|
+
多页 `.html` + localStorage 已经能覆盖绝大多数应用形态。**跨页状态靠 localStorage,
|
|
127
|
+
不是靠前端路由** —— 用户在列表页勾的筛选、登录态、购物车,跳到详情页照样在。
|
|
128
|
+
|
|
129
|
+
这么做的好处是平台的感知层全程有效:`list_pages` 看得到结构、按页截图、按页刷新、
|
|
130
|
+
整站导出、发布后深链接都不瞎。SPA + 客户端路由会让这些**全部失明**(硬约束见
|
|
131
|
+
`build-lane.md` 第 2 条),先别走那条。
|
|
132
|
+
|
|
133
|
+
## 交给用户:README 是交付物的一半
|
|
134
|
+
|
|
135
|
+
产物根里必须有 `README.md`。没有它,用户拿到的是一堆他不敢动的文件。
|
|
136
|
+
|
|
137
|
+
```markdown
|
|
138
|
+
# <站名>
|
|
139
|
+
|
|
140
|
+
打开 `index.html` 就能看(不需要装任何东西 / 或:`npm i && npm run build`)。
|
|
141
|
+
|
|
142
|
+
## 现在的数据是假的
|
|
143
|
+
所有数据来自 `app/seed.js`,写操作存在浏览器 localStorage 里(key 前缀 `demo:<站名>:`)。
|
|
144
|
+
清掉浏览器数据就回到初始状态。
|
|
145
|
+
|
|
146
|
+
## 换成真后端要改哪里
|
|
147
|
+
只改 `app/api.js` 一个文件:把每个函数从调用 `mock.js` 改成 `fetch`。页面代码一行不用动。
|
|
148
|
+
|
|
149
|
+
你的后端需要提供这些接口:
|
|
150
|
+
| 函数 | 建议路由 | 入参 | 返回 |
|
|
151
|
+
|---|---|---|---|
|
|
152
|
+
| listPosts | GET /api/posts | `{keyword?, tag?}` | `Post[]` |
|
|
153
|
+
| createPost | POST /api/posts | `{title, body, tags}` | `Post` |
|
|
154
|
+
| login | POST /api/auth/login | `{username, password}` | `{token, user}` |
|
|
155
|
+
|
|
156
|
+
(Post 的字段见 `app/seed.js`)
|
|
157
|
+
|
|
158
|
+
## 登录
|
|
159
|
+
演示账号 `admin / demo`,登录态只是 localStorage 里的一个标记,不是真的鉴权。
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
那张接口表是这条道**最值钱的产出**:它把「用了模拟数据」从缺陷变成资产 —— 用户拿到的
|
|
163
|
+
不只是前端,还有一份现成的后端需求规格。写 `api.js` 时顺手就攒出来了,别到最后才补。
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 页面转场与客户端路由
|
|
2
|
+
|
|
3
|
+
**动手写第一个转场之前看这一页。** 这不是"高级技巧",是一个结构决定:
|
|
4
|
+
上了转场之后,页面脚本从"跑一遍"变成"跑很多遍",而把单遍执行的脚本回头改成
|
|
5
|
+
可重入的,比一开始就分两段贵得多。
|
|
6
|
+
|
|
7
|
+
## 结构:boot / initPage / AbortController
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// script.js —— 任何打算上转场或路由的站从这个骨架起手
|
|
11
|
+
const ac = { current: null };
|
|
12
|
+
|
|
13
|
+
/** 只跑一次:全局的、跟具体页面无关的东西 */
|
|
14
|
+
function boot() {
|
|
15
|
+
document.addEventListener('click', onLinkClick); // 路由拦截,全局一份
|
|
16
|
+
initPage(); // 首屏也要走一遍
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 每次进入一个页面都跑:这一页的观察者、动效、交互 */
|
|
20
|
+
function initPage() {
|
|
21
|
+
// ⭐ 上一页挂的 window / document 监听全部一次性摘掉。
|
|
22
|
+
// 不摘的话翻十页就有十份 scroll 监听在跑,页面越用越卡,
|
|
23
|
+
// 而且旧监听指着已经被替换掉的 DOM。
|
|
24
|
+
ac.current?.abort();
|
|
25
|
+
ac.current = new AbortController();
|
|
26
|
+
const { signal } = ac.current;
|
|
27
|
+
|
|
28
|
+
window.addEventListener('scroll', onScroll, { signal });
|
|
29
|
+
window.addEventListener('resize', onResize, { signal });
|
|
30
|
+
|
|
31
|
+
// IntersectionObserver 之类是页面级的,重新建
|
|
32
|
+
const io = new IntersectionObserver(reveal, { threshold: 0.2 });
|
|
33
|
+
document.querySelectorAll('.rv').forEach(el => io.observe(el));
|
|
34
|
+
signal.addEventListener('abort', () => io.disconnect());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
boot();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
判据很简单:**这段代码在同一个 tab 里连续跑五次,行为要和跑第一次一样。**
|
|
41
|
+
|
|
42
|
+
## 路由本体
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
async function onLinkClick(e) {
|
|
46
|
+
const a = e.target.closest('a[href]');
|
|
47
|
+
if (!a) return;
|
|
48
|
+
const url = new URL(a.href, location.href);
|
|
49
|
+
if (url.origin !== location.origin) return; // 外链照常
|
|
50
|
+
if (!/\.html?$/.test(url.pathname)) return; // 只接站内页面
|
|
51
|
+
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
const html = await fetch(url).then(r => r.text());
|
|
54
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
55
|
+
document.querySelector('main').replaceWith(doc.querySelector('main'));
|
|
56
|
+
document.title = doc.title;
|
|
57
|
+
history.pushState(null, '', url);
|
|
58
|
+
window.scrollTo(0, 0);
|
|
59
|
+
initPage(); // ⭐ 别忘了这一句
|
|
60
|
+
}
|
|
61
|
+
window.addEventListener('popstate', () => location.reload()); // 后退最省事的正确做法
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## ⚠️ file:// 那道守卫要不要写
|
|
65
|
+
|
|
66
|
+
以前站点自检走 `file://`,`fetch` 必然被 CORS 拒,所以这类脚本里常见一条
|
|
67
|
+
「`location.protocol` 不是 http 就关掉路由、退回原生跳转」的守卫。
|
|
68
|
+
|
|
69
|
+
**现在 `screenshot_canvas` 已经走 http(跟用户预览同源),自检时路由是活的。**
|
|
70
|
+
但导出的 zip 用户在本地双击打开仍然是 `file://` —— 所以这条守卫**还是要写**,
|
|
71
|
+
它保护的是那个场景:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const routerOk = location.protocol === 'http:' || location.protocol === 'https:';
|
|
75
|
+
if (routerOk) document.addEventListener('click', onLinkClick);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
不写的话导出包里点任何链接都是白屏。
|
|
79
|
+
|
|
80
|
+
## 帘幕/遮罩转场的两个坑
|
|
81
|
+
|
|
82
|
+
- **静止态要藏在视口外**(`position:fixed; inset:0; transform:translateY(100%)`),
|
|
83
|
+
别用 `display:none` 切 —— 那样没有过渡可言
|
|
84
|
+
- ⚠️ **`fullPage` 截图会把它画在页面中段**:视口被撑成整页高,`translateY(100%)`
|
|
85
|
+
就是往下推一整个展开视口。看起来像一大块盖住内容的色块,而它其实是正常的。
|
|
86
|
+
要看它的真实位置用 `screenshot_canvas` 的 `scrollTo` 参数(真滚视口再抓一帧)
|