gitoriaLog in with ident

gitoria

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit4a2d71254a2d7125initial commitmre4a2d7125/plugins/web/README.md

5.9 KB

  1. # hl:web — the web framework
  2. `hl:web` serves an app's pages from the server and keeps them live in the browser. It is written
  3. in Hybriel: `WebFramework.hl` is the server half, `client.hl` the browser half, and `compile.hl`
  4. turns each component's View into that component's own code. The model behind it (components,
  5. Views, realms, the boundary) is in [COMPONENTS.md](../../COMPONENTS.md). This page lists the rules
  6. an app is held to. Each rule is a located refusal at boot unless it says otherwise.
  7. ## Starting an app
  8. ```hybriel
  9. import WebFramework from 'hl:web'
  10. import Home from './components/home.hl'
  11. import Styles from './styles.hl'
  12. routes = [ { pattern = "/" component = Home } ]
  13. server = new WebFramework(routes = routes, styles = Styles, port = 8080)
  14. ```
  15. Settings may be passed as named arguments. Most of them may instead be members of the file that
  16. runs the `new`:
  17. | setting | default | meaning |
  18. |---|---|---|
  19. | `routes` | `[]` | the route table (below); pass it as an argument |
  20. | `styles` | none | the app's styles file: the imported class, or a path string. It must be in the project graph |
  21. | `port` | 8080 | the port to listen on |
  22. | `host` | `HL_HOST`/`HOST`, else 0.0.0.0 | the interface to bind |
  23. | `audience` | `{}` | per outward event, who receives it (see Events) |
  24. | `minify` | false | one-line HTML and compact modules |
  25. | `watchMode` | true | a saved `.hl` file re-analyses the app and reloads every open tab |
  26. | `sessionDir` | `<app>/.sessions` | where sessions are stored; `false` keeps them in memory |
  27. | `sessionMaxAge`, `sessionIdle`, `sweepInterval` | 14 days, 15 min, 5 min | the session clocks, in seconds |
  28. | `sessionCookie` | `hlsid` | the cookie's name: letters, digits, `-` and `_` |
  29. | `sessionSecure` | false | set the cookie's `Secure` flag (for an app behind https) |
  30. | `appTitle`, `appDescription`, `appImage`, `appFavicon`, `meta` | none | the head every page gets unless it declares its own |
  31. An app runs on one web framework. If its files reach two packages that hold a `WebFramework.hl`
  32. (for example an old vendored copy beside this one), it is refused at boot, naming the import row
  33. of each.
  34. ## Routes
  35. Each entry has a `pattern` (`/posts/:id`, `/assets/*`) and one kind:
  36. | kind | answers with |
  37. |---|---|
  38. | `component = Home` or `"./components/home.hl"` | the page, rendered on the server; the component must be imported by the app, and must declare a View |
  39. | `function = (route, req) => { … }` | what the function returns (a Hybrid becomes JSON); `req.session` is the cookie's session, or null |
  40. | `direct = "text"` | that text |
  41. | `file = "./x"` | one file |
  42. | `directory = "./assets"` | the files under a directory |
  43. A named group (`:id`) reaches the component as a construction argument of the same name: declare
  44. `id = null` at its root. A named wildcard does the same with the rest of the path:
  45. `/code/*path` gives `path = 'src/lib/util.hl'` for `/code/src/lib/util.hl`, on the first load and
  46. on a navigation. A bare `*` has no name a member could take; it is what a `directory` route
  47. serves from.
  48. ## Components
  49. A component is a `.hl` file with a `View`. Its root members are its state, and are constructed on
  50. the server for each request.
  51. **A View attribute is a literal, a member or a field path.** `href = "/"`, `href = url` and
  52. `href = p.url` are allowed. `href = '/posts/' + id` is refused at its line: declare
  53. `postUrl = '/posts/' + id` at the file's root and write `href = postUrl`. The same holds for a
  54. value bound on a component reference (`Card { title = t }`) and for the condition of an `if` in a
  55. View, which may also be a `for` row variable.
  56. **The tree carries the elements the HTML parser implies.** `table { tr { td { … } } }` is rendered
  57. as `table > tbody > tr > td`, because that is the tree the browser builds from the HTML, and the
  58. page is continued from the tree the browser built. The pairs are listed in `view.hl`
  59. (`impliedElements`): `tr`, `td` and `th` under `table` get a `tbody`, `td` and `th` under `tbody`,
  60. `thead` or `tfoot` get a `tr`, and `col` gets a `colgroup`. Consecutive children that need the same
  61. container share one.
  62. The other rules:
  63. - A View reads only names the file declares. A name it declares nowhere is refused.
  64. - `parent './main.hl'` wraps a page in a shell. The shell declares `slot = null` and places
  65. `slot` in its View exactly once. A component that is filled (`Card { p { … } }`) must declare a
  66. slot too.
  67. - `body { … }` is allowed only as the root of a View, and a page wrapped by a parent cannot have
  68. one: the shell owns the body.
  69. - A View cannot render itself, directly or through other components.
  70. - A Style rule cannot be written on a component reference. Write it on an element inside that
  71. component.
  72. - A page's head comes from its members `__title`, `__description`, `__image`, `__favicon` and
  73. `__meta`, and falls back to the app's `appTitle`, `appDescription`, `appImage`, `appFavicon` and
  74. `meta`. A handler that writes one of them updates the document.
  75. ## Events
  76. `on name(…)` handlers and `emit` statements cross between the browser and the server over a
  77. WebSocket on the app's own port. `POST /__hl/emit` is the fallback for a peer without a socket.
  78. A handler that takes `session` as its last parameter gets the connection's session from the
  79. server, never from the peer.
  80. An outward event reaches the tab that caused it. To send it to other connections, give it an
  81. `audience` entry: a function of the event's arguments and the receiving connection's session that
  82. answers true or false.
  83. A value-form emit (`answer = emit server ask()`) waits for one answer, so it has one answerer.
  84. If two files in the target realm answer the event, it is refused.
  85. ## What it serves
  86. | url | what |
  87. |---|---|
  88. | `/<file key>` (e.g. `/components/home.hl`) | a component's browser module |
  89. | `/__hl/hl-runtime.js` | the runtime every module imports |
  90. | `/__hl/web/client.js` | this package's browser half (other packages' halves are at `/__hl/<name>/client.js`) |
  91. | `/__hl/app.css` | the one stylesheet, built from the styles file and every component's `Style` |
  92. | `/__hl/emit` | the POST fallback for emits |

Branches

Latest commits

  • 4a2d7125initial commitmre