Repository navigation
Conversation
NSH adds a view prop of the web, `web={{ element }}`: the HTML element
the web draws a view or text as where `role` cannot say it (`p`, `nav`,
`article`, `time`, ...). The checker prints it with the other mounted
props, so the case that sets it can check it.
It is behind `nsh_has_web_element`, detected in `build.rs` from the host
props as `windowControl` is, so the checker still builds against NSH
checkouts without it and this can merge on its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 tasks done
huacnlee
added a commit
to longbridge/nsh
that referenced
this pull request
Nov 9, 2026
…1130) ## Description Sites published with `nsh package --target web` are single pages to a browser and to search engines: links are no `<a href>`, every page has the app's title and no description, the markup is `div`s, and a right click on a link offers nothing. This makes a published app a site: - **Document elements.** The web draws a view or text as the HTML element its props say it is: `role="header"` is `h1`–`h6` by `accessibilityLevel` (`h2` without one), a `Link` with an `href` is `<a href>` (from the `href` prop `Link` already sends its view, #1289), and `web={{ element }}` names only what `role` cannot say (`p`, `nav`, `header`, `footer`, `main`, `article`, `section`, `aside`, `ul`, `ol`, `li`, `strong`, `em`, `blockquote`, `figure`, `figcaption`, `time`, `address`). A plain click on a link stays the app's (`Link`'s `onOpen`); a click with a modifier or the middle button opens `href`; a right click shows the browser's link menu unless the app shows its own (`onContextMenu`). Other platforms ignore `web={{ element }}`. - **The page's head.** `nsh/web`'s `Head` sets the title, description, canonical URL, language, meta and JSON-LD while it is mounted; a later one wins for what it sets. Native hosts render nothing for it. - **Data the page was served with.** `runModule(code, { params })` gives the app its `host.params` on the web as the native hosts do, and the packaged page passes the JSON of a `<script type="application/json" id="nsh-params">` it carries, so a server that already has the first screen's data hands it over with the page. A URL for each page is #982's: `UrlScheme.url()` / `setUrl` and `NavStack`'s `onChange`, with the app mapping its routes to addresses. An earlier `NavStack` `linking` prop is removed from this PR (`ab92b96b`), following review. The text fix this PR carried is #1225, merged on its own. No rendering on a server is part of this; pages still render in the browser. ## Public API - `web={{ element?: WebElement }}` on every view and text (`WebHostProps`; `WebElement` = `"p" | "nav" | "header" | "footer" | "main" | "article" | "section" | "aside" | "ul" | "ol" | "li" | "strong" | "em" | "blockquote" | "figure" | "figcaption" | "time" | "address"`): the HTML element the web draws it as where `role` cannot say it. - Rust: `nsh_core::WebElement`, `Prop::WebElement(Option<WebElement>)`, `ViewProps::web_element`, builder method `.web_element(WebElement)`. - Module `nsh/web`: `Head(props: HeadProps): JSX.Element`, `HeadProps { title?, description?, canonical?, lang?, meta?: HeadMeta[], jsonLd? }`, `HeadMeta { name?, property?, content }`. - Web runtime: `Player.runModule(entry, { params })`; wasm export `nsh_set_host_params(ptr, len)` (internal, named only in `docs/dev/web.md`). - Packaged web page: reads `<script type="application/json" id="nsh-params">` as the app's `host.params`. No new top-level props: headings and links come from the existing `role` / `accessibilityLevel` and `Link`'s `href`. ## How to Test - `cargo test -p nsh-core -p nsh-js` (`web_element_is_a_view_prop`, `nsh/web`'s declarations, `WebHostProps`). - `node --test crates/nsh-platform-web/web/nsh.test.mjs crates/nsh-platform-web/web/browser/page.test.mjs` (the element of a heading, a link and `web={{ element }}`; heads; a link's context menu). - `cargo xtask compat`: `browser`'s `props-view-web-element`, `modules`' `mod-web`. The `web.element` steps need longbridge/nsh-compat#42 (the checker prints `element`); it builds against `main` too, so it can merge first. - By hand: `nsh package <app> --target web --run` with an app using them; view the source (Cmd+Option+U), check the head, right click a link. ## Checklist - [x] Docs: `docs/dev/web.md`, `docs/dev/elements.md`, `docs/dev/js-modules.md`, `website/` (English and zh-CN). - [x] Compat cases for the new API. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: tzyito <zhiyong.tian@longbridge-inc.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Jason Lee <huacnlee@gmail.com>
3 of 5 tasks
This was referenced Nov 9, 2026
madcodelife
added a commit
that referenced
this pull request
Nov 9, 2026
longbridge/nsh#1323 put `EmojiPicker` behind nsh-base's `emoji-picker` feature. NSH's own compat run passes `--features nsh-base/emoji-picker`, but this repository's CI runs plain `cargo test`. As a result, the base and gallery apps fail to load ("Could not find export 'EmojiPicker' in module 'nsh/base'"), and `checkout_apps_run` fails, on `main` since dae4166 and on #42. This change declares the feature in the manifest, as #33 did for `shader`. That fixes CI and local runs alike. Verified locally on macOS against NSH main (fc8058ed) with #42 merged in. With the feature on and longbridge/nsh#1431 applied, `cargo test` passes 32/32. #1431 fixes an engine panic in `cancel_press` that the same apps hit next. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Thank you, @Tzyito! #43 landed the same change a few hours earlier ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
NSH adds a view prop of the web,
web={{ element }}(longbridge/nsh#1130): the HTML element the web draws a view or text as whererolecannot say it (p,nav,article,time, ...). The checker prints it with the other mounted props, so the case that sets it can check it.It is behind
nsh_has_web_element, detected inbuild.rsfrom the host props aswindowControlis, so the checker still builds against NSH checkouts without it and this can merge on its own.How to test
NSH_COMPAT_APP=browser cargo xtask compatin an NSH checkout of longbridge/nsh#1130 (feat/web-pages): theprops-view-web-elementsteps printelement(article,time,p) and pass.modulesandpropspass too.🤖 Generated with Claude Code