URL restructure, 404 page, trailing slash normalization, layout fixes

- Rename /reactive-islands/ → /reactive/, /reference/ → /hypermedia/reference/,
  /examples/ → /hypermedia/examples/ across all .sx and .py files
- Add 404 error page (not-found.sx) working on both server refresh and
  client-side SX navigation via orchestration.sx error response handling
- Add trailing slash redirect (GET only, excludes /api/, /static/, /internal/)
- Remove blue sky-500 header bar from SX docs layout (conditional on header-rows)
- Fix 405 on API endpoints from trailing slash redirect hitting POST/PUT/DELETE
- Fix client-side 404: orchestration.sx now swaps error response content
  instead of silently dropping it
- Add new plan files and home page component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 21:30:18 +00:00
parent e149dfe968
commit 1341c144da
35 changed files with 2305 additions and 438 deletions

View File

@@ -339,6 +339,7 @@ class JSEmitter:
"dom-remove-children-after": "domRemoveChildrenAfter",
"dom-set-data": "domSetData",
"dom-get-data": "domGetData",
"dom-inner-html": "domInnerHtml",
"json-parse": "jsonParse",
"dict-has?": "dictHas",
"has-key?": "dictHas",
@@ -2966,6 +2967,9 @@ PLATFORM_DOM_JS = """
function domGetData(el, key) {
return (el && el._sxData) ? (el._sxData[key] != null ? el._sxData[key] : nil) : nil;
}
function domInnerHtml(el) {
return (el && el.innerHTML != null) ? el.innerHTML : "";
}
function jsonParse(s) {
try { return JSON.parse(s); } catch(e) { return {}; }
}
@@ -3854,11 +3858,17 @@ PLATFORM_ORCHESTRATION_JS = """
}
function stripSxScripts(text) {
// Strip <script type="text/sx">...</script> (without data-components).
// Strip <script type="text/sx">...</script> (without data-components or data-init).
// These contain extra component defs from streaming resolve chunks.
// data-init scripts are preserved for process-sx-scripts to evaluate as side effects.
var SxObj = typeof Sx !== "undefined" ? Sx : null;
return text.replace(/<script[^>]*type="text\\/sx"[^>]*>([\\s\\S]*?)<\\/script>/gi,
function(_, defs) { if (SxObj && SxObj.loadComponents) SxObj.loadComponents(defs); return ""; });
return text.replace(/<script[^>]*type="text\\/sx"[^>]*>[\\s\\S]*?<\\/script>/gi,
function(match) {
if (/data-init/.test(match)) return match; // preserve data-init scripts
var m = match.match(/<script[^>]*>([\\s\\S]*?)<\\/script>/i);
if (m && SxObj && SxObj.loadComponents) SxObj.loadComponents(m[1]);
return "";
});
}
function extractResponseCss(text) {
@@ -4115,7 +4125,8 @@ def fixups_js(has_html, has_sx, has_dom, has_signals=False):
if (typeof domMatches === "function") PRIMITIVES["dom-matches?"] = domMatches;
if (typeof preventDefault_ === "function") PRIMITIVES["prevent-default"] = preventDefault_;
if (typeof elementValue === "function") PRIMITIVES["element-value"] = elementValue;
if (typeof domOuterHtml === "function") PRIMITIVES["dom-outer-html"] = domOuterHtml;''')
if (typeof domOuterHtml === "function") PRIMITIVES["dom-outer-html"] = domOuterHtml;
if (typeof domInnerHtml === "function") PRIMITIVES["dom-inner-html"] = domInnerHtml;''')
return "\n".join(lines)