Skip to content

Commit 971112c

Browse files
bartlomiejuclaude
andcommitted
merge main, resolve test conflicts
Keep main's new tests and append view transition tests after them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 parents 24fb6ea + dc23248 commit 971112c

57 files changed

Lines changed: 1881 additions & 258 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ jobs:
1515
env:
1616
TITLE: ${{ github.event.pull_request.title }}
1717
run: |
18-
if ! echo "$TITLE" | grep -qP '^(chore|ci|docs|feat|fix|refactor|test):'; then
19-
echo "::error::PR title must start with chore:, ci:, docs:, feat:, fix:, refactor: or test:"
18+
if ! echo "$TITLE" | grep -qP '^(chore|ci|docs|feat|fix|perf|refactor|test):'; then
19+
echo "::error::PR title must start with chore:, ci:, docs:, feat:, fix:, perf:, refactor: or test:"
2020
exit 1
2121
fi
2222

deno.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"@std/collections": "jsr:@std/collections@^1.1.2",
4949
"@std/dotenv": "jsr:@std/dotenv@^0.225.5",
5050
"@std/http": "jsr:@std/http@^1.0.15",
51+
"@std/net": "jsr:@std/net@^1.0.6",
5152
"@std/uuid": "jsr:@std/uuid@^1.0.7",
5253
"@supabase/postgrest-js": "npm:@supabase/postgrest-js@^1.21.4",
5354
"@types/mime-db": "npm:@types/mime-db@^1.43.6",

deno.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/latest/advanced/app-wrapper.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default define.page(({ Component, url }) => {
4747

4848
When building your app with `new App()` instead of file-based routing:
4949

50-
```tsx main.tsx
50+
```tsx
5151
function AppWrapper({ Component }) {
5252
return (
5353
<html lang="en">

docs/latest/advanced/error-handling.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Fresh supports two kind of error pages:
2121
To add an error page use [`app.onError()`](/docs/concepts/app#onerror).
2222

2323
```ts main.ts
24+
import { App } from "fresh";
25+
2426
const app = new App()
2527
.onError("*", (ctx) => {
2628
console.log(`Error: ${ctx.error}`);
@@ -36,7 +38,7 @@ will be invoked.
3638

3739
You can also nest error pages:
3840

39-
```ts main.ts
41+
```ts
4042
const app = new App()
4143
// Top level error page
4244
.onError("*", (ctx) => {
@@ -56,7 +58,7 @@ Not found errors are often treated differently than generic errors. You can both
5658
treat them with the `.onError()` way, but by adding a specific `.notFound()`
5759
handler, Fresh ensures that every 404 error will invoke this callback.
5860

59-
```ts main.ts
61+
```ts
6062
const app = new App()
6163
// Top level error page
6264
.notFound((ctx) => {
@@ -103,7 +105,7 @@ async function authMiddleware(ctx) {
103105
When an `HttpError` is thrown, Fresh catches it and invokes the error handler.
104106
You can check the status code in your error handler:
105107

106-
```ts main.ts
108+
```ts
107109
import { HttpError } from "fresh";
108110

109111
app.onError("*", (ctx) => {

docs/latest/advanced/head.md

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ export default define.page((ctx) => {
4343
For more complex scenarios, or to set page metadata from
4444
[islands](/docs/concepts/islands), Fresh ships with the `<Head>`-component.
4545

46-
> [info]: The `<Head>` component is not dynamic by default. It will not
47-
> automatically update the document title or other head elements on the client
48-
> side when component state changes. The head elements are set during server
49-
> rendering or initial page load.
50-
5146
```tsx routes/about.tsx
5247
import { Head } from "fresh/runtime";
5348

@@ -64,6 +59,29 @@ export default define.page((ctx) => {
6459
});
6560
```
6661

62+
### Dynamic head updates from islands
63+
64+
The `<Head>` component works in [islands](/docs/concepts/islands) too. When
65+
component state changes, the document head is updated automatically:
66+
67+
```tsx islands/MetaUpdater.tsx
68+
import { useState } from "preact/hooks";
69+
import { Head } from "fresh/runtime";
70+
71+
export default function MetaUpdater() {
72+
const [title, setTitle] = useState("Welcome");
73+
74+
return (
75+
<div>
76+
<Head>
77+
<title>{title}</title>
78+
</Head>
79+
<button onClick={() => setTitle("Updated!")}>Change title</button>
80+
</div>
81+
);
82+
}
83+
```
84+
6785
### Avoiding duplicate tags
6886

6987
You might end up with duplicate tags, when multiple `<Head />` components are
@@ -75,13 +93,15 @@ the matching element:
7593
3. Check if an element with the same `id` attribute
7694
4. Only for `<meta>` elements: Check if there is a `<meta>` element with the
7795
same `name` attribute
78-
5. No matching element was found, Fresh will create a new one and append it to
96+
5. Only for `<link>` elements: Check if there is a `<link>` element with the
97+
same `rel` attribute
98+
6. No matching element was found, Fresh will create a new one and append it to
7999
`<head>`
80100

81101
When multiple `<Head>` components render an element with the same key, the
82-
**last one rendered wins**. Since Fresh renders top-down (app wrapper layout
83-
route page component), a route page can override defaults set in `_app.tsx` by
84-
using the same `key` prop.
102+
**last one rendered wins**. Since Fresh renders top-down (app wrapper -> layout
103+
-> route -> page component), a route page can override defaults set in
104+
`_app.tsx` by using the same `key` prop.
85105

86106
> [info]: The `<title>`-tag is automatically deduplicated, even without a `key`
87107
> prop.

docs/latest/advanced/layouts.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ HTML structure and only the content changes, a layout is a neat way to abstract
1212
this. Layouts only ever render on the server. The passed `Component` value
1313
represents the children of this component.
1414

15-
```tsx main.tsx
15+
```tsx
1616
function PageLayout({ Component }) {
1717
return (
1818
<div>
@@ -42,7 +42,7 @@ You can register multiple layouts for different paths. Layouts are inherited
4242
from parent paths - a layout at `"*"` applies to all routes, and more specific
4343
layouts are added on top:
4444

45-
```ts main.ts
45+
```ts
4646
const app = new App()
4747
.layout("*", MainLayout) // Applied to all routes
4848
.layout("/admin/*", AdminLayout) // Added on top for /admin/* routes
@@ -69,6 +69,6 @@ const app = new App()
6969

7070
Ignore the [app wrapper](/docs/concepts/app) component:
7171

72-
```ts main.ts
72+
```ts
7373
app.layout("/foo/bar", MyComponent, { skipAppWrapper: true });
7474
```

docs/latest/advanced/opentelemetry.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,25 @@ deno task start
127127

128128
Open `http://localhost:16686` to browse traces. You'll see each request broken
129129
down into its middleware, handler, and rendering spans.
130+
131+
## Client-side trace correlation
132+
133+
When an OpenTelemetry exporter is active, Fresh automatically injects a
134+
[W3C Trace Context](https://www.w3.org/TR/trace-context/) `<meta>` tag into the
135+
`<head>` of every rendered page:
136+
137+
```html
138+
<head>
139+
<meta
140+
name="traceparent"
141+
content="00-ab42124a3c573678d4d8b21ba52df3bf-d21f7bc17caa5aba-01"
142+
>
143+
<!-- ... -->
144+
</head>
145+
```
146+
147+
This allows client-side OpenTelemetry instrumentation (such as
148+
[`@opentelemetry/instrumentation-document-load`](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/c9d62be989802534c01373e8ab41e13747d7ee3e/packages/instrumentation-document-load))
149+
to link browser performance traces back to the server-side span that rendered
150+
the page, giving you end-to-end visibility from server rendering through page
151+
load.

docs/latest/advanced/partials.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ shops for example.
156156
export default function AddToCartPartial() {
157157
return (
158158
<>
159-
<Partial name="cart-items" mode="append">
159+
<Partial name="cart-items" mode="append" key={newItem.id}>
160160
{/* Render the new cart item here */}
161161
</Partial>
162162
<Partial name="total-price">
@@ -187,7 +187,7 @@ export default function LogView() {
187187
const lines = getNewLogLines();
188188

189189
return (
190-
<Partial name="logs-list" mode="append">
190+
<Partial name="logs-list" mode="append" key={lines[0]}>
191191
{lines.map((line) => {
192192
return <li key={line}>{line}</li>;
193193
})}
@@ -196,8 +196,10 @@ export default function LogView() {
196196
}
197197
```
198198

199-
> [info]: When picking the `prepend` or `append` mode, make sure to add keys to
200-
> the elements.
199+
> [warn]: When using `prepend` or `append` mode, you **must** add a `key` prop
200+
> to the `<Partial>` component. Without it, Preact cannot distinguish new
201+
> children from existing ones, leading to subtle rendering bugs. Fresh will log
202+
> a warning if it detects a missing key on an append/prepend partial.
201203
202204
## View Transitions
203205

docs/latest/concepts/app.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ mounted alongside other apps. The base path is available in handlers via
4040
All items are applied from top to bottom. This means that when you defined a
4141
middleware _after_ a `.get()` handler, it won't be included.
4242

43-
```ts main.ts
43+
```ts
4444
const app = new App()
4545
.use((ctx) => {
4646
// Will be called for all middlewares

0 commit comments

Comments
 (0)