Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions babel.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ module.exports = {
[
"babel-plugin-jsx-dom-expressions",
{
moduleName: "solid-js/web",
moduleName: "@solidjs/web",
contextToCustomElements: true,
wrapConditionals: true,
builtIns: ["For", "Show", "Switch", "Match", "Suspense", "SuspenseList", "Portal"]
builtIns: ["For", "Show", "Switch", "Match", "Loading", "Errored", "Portal"]
}
]
]
Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@solidjs/meta",
"description": "Write meta tags to the document head",
"version": "0.29.7",
"version": "0.30.0-next.0",
"author": "Ryan Carniato",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -35,7 +35,8 @@
"release": "pnpm build && changeset publish"
},
"peerDependencies": {
"solid-js": ">=1.8.4"
"solid-js": ">=2.0.0-beta.0 <2.0.0",
"@solidjs/web": ">=2.0.0-beta.0 <2.0.0"
},
"devDependencies": {
"@babel/cli": "^7.27.0",
Expand All @@ -44,15 +45,15 @@
"@babel/preset-typescript": "7.27.0",
"@changesets/cli": "^2.28.1",
"@rollup/plugin-babel": "^6.0.4",
"@solidjs/web": "2.0.0-beta.14",
"@testing-library/jest-dom": "^6.6.3",
"@types/jest": "^29.5.14",
"@vitest/browser": "^3.1.1",
"babel-preset-solid": "^1.9.5",
"@vitest/browser": "^4.1.9",
"babel-preset-solid": "2.0.0-beta.14",
"jsdom": "^26.0.0",
"rimraf": "^6.0.1",
"solid-js": "^1.9.5",
"solid-js": "2.0.0-beta.14",
"typescript": "5.8.3",
"vite-plugin-solid": "^2.11.6",
"vitest": "^3.1.1"
"vite-plugin-solid": "^3.0.0-next.5",
"vitest": "^4.1.9"
}
}
1,039 changes: 391 additions & 648 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
allowBuilds:
esbuild: true
26 changes: 13 additions & 13 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import {
Component,
type Component,
createContext,
createRenderEffect,
createUniqueId,
JSX,
onCleanup,
ParentComponent,
type ParentComponent,
sharedConfig,
useContext
} from "solid-js";
import { escape, isServer, spread, ssr, useAssets } from "solid-js/web";
import { escape, isServer, spread, ssr, useAssets, type JSX } from "@solidjs/web";

export const MetaContext = createContext<MetaContextType>();

Expand Down Expand Up @@ -58,7 +56,7 @@ const getTagKey = (tag: TagDescription, properties: string[]) => {
};

function initClientProvider() {
if (!sharedConfig.context) {
if (!sharedConfig.hydrating) {
const ssrTags = document.head.querySelectorAll(`[data-sm]`);
// `forEach` on `NodeList` is not supported in Googlebot, so use a workaround
Array.prototype.forEach.call(ssrTags, (ssrTag: Node) => ssrTag.parentNode!.removeChild(ssrTag));
Expand Down Expand Up @@ -192,15 +190,15 @@ function initServerProvider() {
tags.push(tagDesc);
return tags.length;
},
removeTag(tag: TagDescription, index: number) {}
removeTag(_tag: TagDescription, _index: number) {}
};
}

export const MetaProvider: ParentComponent = props => {
const actions = !isServer
? initClientProvider()
: initServerProvider();
return <MetaContext.Provider value={actions!}>{props.children}</MetaContext.Provider>;
return <MetaContext value={actions!}>{props.children}</MetaContext>;
};

const MetaTag = (
Expand All @@ -223,12 +221,14 @@ const MetaTag = (

export function useHead(tagDesc: TagDescription) {
const c = useContext(MetaContext);
if (!c) throw new Error("<MetaProvider /> should be in the tree");

createRenderEffect(() => {
const index = c!.addTag(tagDesc);
onCleanup(() => c!.removeTag(tagDesc, index));
});
createRenderEffect(
() => tagDesc,
tag => {
const index = c.addTag(tag);
return () => c.removeTag(tag, index);
}
);
}

function renderTags(tags: Array<TagDescription>) {
Expand Down
31 changes: 22 additions & 9 deletions test/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* @jsxImportSource solid-js */
import { createSignal, getOwner, lazy } from "solid-js";
import { hydrate, render, Show } from "solid-js/web";
import { createSignal, flush, getOwner, lazy, Loading, Show } from "solid-js";
import { hydrate, render } from "@solidjs/web";
import { MetaProvider, Title, Style, Meta, Link, Base } from "../src";
import { hydrationScript, removeScript } from "./hydration_script";
import { describe, test, expect, beforeEach, afterEach } from "vitest";
import { test, expect, beforeEach, afterEach } from "vitest";

beforeEach(() => {
document.head.innerHTML = "";
Expand Down Expand Up @@ -85,6 +84,7 @@ test("unmount middle child, should show only the last title", () => {
);
expect(document.head.innerHTML).toBe(snapshot);
setVisible(false);
flush();
expect(document.head.innerHTML).toBe(snapshot);
dispose();
});
Expand Down Expand Up @@ -114,6 +114,7 @@ test("unmount last child, should show only the second last title", () => {
);
expect(document.head.innerHTML).toBe(snapshot1);
setVisible(false);
flush();
expect(document.head.innerHTML).toBe(snapshot2);
dispose();
});
Expand Down Expand Up @@ -163,8 +164,10 @@ test("mounts and unmounts title", () => {

expect(document.head.innerHTML).toBe(snapshot1);
setVisible(true);
flush();
expect(document.head.innerHTML).toBe(snapshot2);
setVisible(false);
flush();
expect(document.head.innerHTML).toBe(snapshot1);
dispose();
});
Expand All @@ -190,8 +193,10 @@ test("hydrates and unmounts title", () => {

expect(document.head.innerHTML).toBe(snapshot1);
setVisible(true);
flush();
expect(document.head.innerHTML).toBe(snapshot2);
setVisible(false);
flush();
expect(document.head.innerHTML).toBe(snapshot1);
dispose();
removeScript();
Expand Down Expand Up @@ -219,9 +224,11 @@ test("switches between titles", async () => {
() => (
<MetaProvider>
<Title>Static</Title>
<Show when={visible()} fallback={<Comp2 />}>
<Comp1 />
</Show>
<Loading fallback={null}>
<Show when={visible()} fallback={<Comp2 />}>
<Comp1 />
</Show>
</Loading>
</MetaProvider>
),
div
Expand All @@ -230,6 +237,7 @@ test("switches between titles", async () => {
await new Promise(resolve => setTimeout(resolve, 1));
expect(document.head.innerHTML).toBe(snapshot1);
setVisible(false);
flush();
await new Promise(resolve => setTimeout(resolve, 1));
expect(document.head.innerHTML).toBe(snapshot2);
dispose();
Expand Down Expand Up @@ -268,14 +276,18 @@ test("renders only the last meta with the same name", () => {
expect(document.head.innerHTML).toBe(snapshot1);
// mount first
setVisible1(true);
flush();
expect(document.head.innerHTML).toBe(snapshot2);
// mount second
setVisible2(true);
flush();
expect(document.head.innerHTML).toBe(snapshot3);
// unmount second
setVisible2(false);
flush();
// unmount first
setVisible1(false);
flush();
expect(document.head.innerHTML).toBe(snapshot1);
dispose();
});
Expand Down Expand Up @@ -322,15 +334,15 @@ test("throws error if head tag is rendered without MetaProvider", () => {
expect(() => {
let div = document.createElement("div");
render(() => <Style>{`body {}`}</Style>, div);
}).toThrowError(/<MetaProvider \/> should be in the tree/);
}).toThrowError(/Context must either be created with a default value/);
});

test("doesn't create any effect on removal", () => {
let div = document.createElement("div");

const [show, setShow] = createSignal(true);
const showAndTest = () => {
expect(getOwner()?.owner).toBeTruthy();
expect(getOwner()?._parent).toBeTruthy();
return show();
};

Expand All @@ -348,6 +360,7 @@ test("doesn't create any effect on removal", () => {
);

setShow(false);
flush();
dispose();
});

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"jsxImportSource": "solid-js"
"jsxImportSource": "@solidjs/web"
},
"include": [
"./src"
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"strict": true,
"lib": ["dom", "esnext", "dom.iterable"],
"jsx": "preserve",
"jsxImportSource": "solid-js"
"jsxImportSource": "@solidjs/web"
},
"include": [
"./test"
Expand Down