Serve sculpt studio at /sculpt
Keep existing viewer URLs compatible and test embedded pages, assets, and isolation headers. Amp-Thread-ID: https://ampcode.com/threads/T-01a0b4b4-202c-73f1-984d-9a55c88f9c83 Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
@@ -89,6 +89,8 @@ func (app *application) routes() http.Handler {
|
|||||||
mux.HandleFunc("/playground/", app.servePlayground)
|
mux.HandleFunc("/playground/", app.servePlayground)
|
||||||
mux.HandleFunc("/view/gltf", app.servePage("gltf.html"))
|
mux.HandleFunc("/view/gltf", app.servePage("gltf.html"))
|
||||||
mux.HandleFunc("/view/gltf/", app.servePage("gltf.html"))
|
mux.HandleFunc("/view/gltf/", app.servePage("gltf.html"))
|
||||||
|
mux.HandleFunc("/sculpt", app.servePage("assets/sculpt/index.html"))
|
||||||
|
mux.HandleFunc("/sculpt/", app.servePage("assets/sculpt/index.html"))
|
||||||
mux.HandleFunc("/view/sculpt", app.servePage("assets/sculpt/index.html"))
|
mux.HandleFunc("/view/sculpt", app.servePage("assets/sculpt/index.html"))
|
||||||
mux.HandleFunc("/view/sculpt/", app.servePage("assets/sculpt/index.html"))
|
mux.HandleFunc("/view/sculpt/", app.servePage("assets/sculpt/index.html"))
|
||||||
mux.HandleFunc("/", app.serveHome)
|
mux.HandleFunc("/", app.serveHome)
|
||||||
|
|||||||
@@ -217,6 +217,46 @@ func TestSavedPlaygroundPageRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSculptRoutesAndAssets(t *testing.T) {
|
||||||
|
routes := testApplication(t).routes()
|
||||||
|
for _, path := range []string{"/sculpt", "/sculpt/", "/view/sculpt", "/view/sculpt/", "/assets/sculpt/app.js", "/assets/sculpt/styles.css"} {
|
||||||
|
t.Run(path, func(t *testing.T) {
|
||||||
|
response := httptest.NewRecorder()
|
||||||
|
routes.ServeHTTP(response, httptest.NewRequest(http.MethodGet, path, nil))
|
||||||
|
if response.Code != http.StatusOK {
|
||||||
|
t.Fatalf("status = %d", response.Code)
|
||||||
|
}
|
||||||
|
for name, expected := range map[string]string{
|
||||||
|
"Cross-Origin-Opener-Policy": "same-origin",
|
||||||
|
"Cross-Origin-Embedder-Policy": "require-corp",
|
||||||
|
} {
|
||||||
|
if got := response.Header().Get(name); got != expected {
|
||||||
|
t.Fatalf("%s = %q, want %q", name, got, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch path {
|
||||||
|
case "/assets/sculpt/app.js", "/assets/sculpt/styles.css":
|
||||||
|
expected := "text/javascript; charset=utf-8"
|
||||||
|
if filepath.Ext(path) == ".css" {
|
||||||
|
expected = "text/css; charset=utf-8"
|
||||||
|
}
|
||||||
|
if response.Header().Get("Content-Type") != expected || response.Body.Len() == 0 {
|
||||||
|
t.Fatalf("missing asset or wrong content type: %q", response.Header().Get("Content-Type"))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if got := response.Header().Get("Content-Type"); got != "text/html; charset=utf-8" {
|
||||||
|
t.Fatalf("content type = %q", got)
|
||||||
|
}
|
||||||
|
for _, content := range []string{"<title>Sculpt — Yawn</title>", `src="/assets/sculpt/app.js"`, `href="/assets/sculpt/styles.css"`, `"@yawn/core": "/pkg/core.js"`} {
|
||||||
|
if !bytes.Contains(response.Body.Bytes(), []byte(content)) {
|
||||||
|
t.Fatalf("sculpt page missing %q", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGltfViewerPageRoute(t *testing.T) {
|
func TestGltfViewerPageRoute(t *testing.T) {
|
||||||
request := httptest.NewRequest(http.MethodGet, "/view/gltf", nil)
|
request := httptest.NewRequest(http.MethodGet, "/view/gltf", nil)
|
||||||
response := httptest.NewRecorder()
|
response := httptest.NewRecorder()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Yawn Sculpt
|
# Yawn Sculpt
|
||||||
|
|
||||||
Open `/view/sculpt` on the Yawn server (`npm run server`). All example code lives here; the only integration outside this folder is the embedded-page route in `server/app.go`. Rendering imports **only `@yawn/core`**. No handles, third-party scene graph, or remote document storage.
|
Open `/sculpt` on the Yawn server (`npm run server`); `/view/sculpt` remains a compatibility alias. The production Docker image embeds this example, so the existing main-branch deployment poller publishes it at `/sculpt` with each deployment. All example code lives here; the only integration outside this folder is the embedded-page route in `server/app.go`. Rendering imports **only `@yawn/core`**. No handles, third-party scene graph, or remote document storage.
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Run explicitly in a fresh /view/sculpt page:
|
// Run explicitly in a fresh /sculpt page:
|
||||||
// await (await import('/assets/sculpt/browser-check.js')).check()
|
// await (await import('/assets/sculpt/browser-check.js')).check()
|
||||||
// Synthetic input checks logic, not physical pen feel. Hooks are always restored.
|
// Synthetic input checks logic, not physical pen feel. Hooks are always restored.
|
||||||
import { Renderer } from "./renderer.js";
|
import { Renderer } from "./renderer.js";
|
||||||
|
|||||||
Reference in New Issue
Block a user