diff --git a/packages/docs/src/routes/api/qwik-testing/api.json b/packages/docs/src/routes/api/qwik-testing/api.json index 42e9a9dec60..6dcf9ee0df7 100644 --- a/packages/docs/src/routes/api/qwik-testing/api.json +++ b/packages/docs/src/routes/api/qwik-testing/api.json @@ -209,7 +209,7 @@ } ], "kind": "Function", - "content": "Trigger an event in unit tests on an element.\n\nFuture deprecation candidate.\n\n\n```typescript\nexport declare function trigger(root: Element, queryOrElement: string | Element | keyof HTMLElementTagNameMap | null, eventName: string, eventPayload?: any, options?: {\n waitForIdle?: boolean;\n}): Promise;\n```\n\n\n\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nroot\n\n\n\n\nElement\n\n\n\n\n\n
\n\nqueryOrElement\n\n\n\n\nstring \\| Element \\| keyof HTMLElementTagNameMap \\| null\n\n\n\n\n\n
\n\neventName\n\n\n\n\nstring\n\n\n\n\n\n
\n\neventPayload\n\n\n\n\nany\n\n\n\n\n_(Optional)_\n\n\n
\n\noptions\n\n\n\n\n{ waitForIdle?: boolean; }\n\n\n\n\n_(Optional)_\n\n\n
\n\n**Returns:**\n\nPromise<void>", + "content": "Trigger an event in unit tests on an element. Needs to be kept in sync with the Qwik Loader event dispatching.\n\nFuture deprecation candidate.\n\n\n```typescript\nexport declare function trigger(root: Element, queryOrElement: string | Element | keyof HTMLElementTagNameMap | null, eventName: string, eventPayload?: any, options?: {\n waitForIdle?: boolean;\n}): Promise;\n```\n\n\n\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nroot\n\n\n\n\nElement\n\n\n\n\n\n
\n\nqueryOrElement\n\n\n\n\nstring \\| Element \\| keyof HTMLElementTagNameMap \\| null\n\n\n\n\n\n
\n\neventName\n\n\n\n\nstring\n\n\n\n\n\n
\n\neventPayload\n\n\n\n\nany\n\n\n\n\n_(Optional)_\n\n\n
\n\noptions\n\n\n\n\n{ waitForIdle?: boolean; }\n\n\n\n\n_(Optional)_\n\n\n
\n\n**Returns:**\n\nPromise<void>", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/testing/element-fixture.ts", "mdFile": "core.trigger.md" }, diff --git a/packages/docs/src/routes/api/qwik-testing/index.mdx b/packages/docs/src/routes/api/qwik-testing/index.mdx index e01dda0acaf..a18320e91ce 100644 --- a/packages/docs/src/routes/api/qwik-testing/index.mdx +++ b/packages/docs/src/routes/api/qwik-testing/index.mdx @@ -499,7 +499,7 @@ superParent: HTMLElement; ## trigger -Trigger an event in unit tests on an element. +Trigger an event in unit tests on an element. Needs to be kept in sync with the Qwik Loader event dispatching. Future deprecation candidate. diff --git a/packages/docs/src/routes/api/qwik/api.json b/packages/docs/src/routes/api/qwik/api.json index 36ab1fa54e4..6981b9f4575 100644 --- a/packages/docs/src/routes/api/qwik/api.json +++ b/packages/docs/src/routes/api/qwik/api.json @@ -2385,7 +2385,7 @@ } ], "kind": "Function", - "content": "Register a listener on the current component's host element.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX. Otherwise, it's adding a JSX listener in the `
` is a better idea.\n\n\n```typescript\nuseOn: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", + "content": "Register a listener on the current component's host element.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX. Otherwise, it's adding a JSX listener in the `
` is a better idea.\n\nEvents are case sensitive.\n\n\n```typescript\nuseOn: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-on.ts", "mdFile": "core.useon.md" }, @@ -2399,7 +2399,7 @@ } ], "kind": "Function", - "content": "Register a listener on `document`.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX.\n\n\n```typescript\nuseOnDocument: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", + "content": "Register a listener on `document`.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX.\n\nEvents are case sensitive.\n\n\n```typescript\nuseOnDocument: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-on.ts", "mdFile": "core.useondocument.md" }, @@ -2413,7 +2413,7 @@ } ], "kind": "Function", - "content": "Register a listener on `window`.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX.\n\n\n```typescript\nuseOnWindow: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", + "content": "Register a listener on `window`.\n\nUsed to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX.\n\nEvents are case sensitive.\n\n\n```typescript\nuseOnWindow: (event: T | T[], eventQrl: EventQRL) => void\n```\n\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nevent\n\n\n\n\nT \\| T\\[\\]\n\n\n\n\n\n
\n\neventQrl\n\n\n\n\nEventQRL<T>\n\n\n\n\n\n
\n\n**Returns:**\n\nvoid", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-on.ts", "mdFile": "core.useonwindow.md" }, diff --git a/packages/docs/src/routes/api/qwik/index.mdx b/packages/docs/src/routes/api/qwik/index.mdx index a14f5da351e..398e00f46ef 100644 --- a/packages/docs/src/routes/api/qwik/index.mdx +++ b/packages/docs/src/routes/api/qwik/index.mdx @@ -9208,6 +9208,8 @@ Register a listener on the current component's host element. Used to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX. Otherwise, it's adding a JSX listener in the `
` is a better idea. +Events are case sensitive. + ```typescript useOn: (event: T | T[], eventQrl: EventQRL) => void ``` @@ -9261,6 +9263,8 @@ Register a listener on `document`. Used to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX. +Events are case sensitive. + ```typescript useOnDocument: (event: T | T[], eventQrl: EventQRL) => void ``` @@ -9314,6 +9318,8 @@ Register a listener on `window`. Used to programmatically add event listeners. Useful from custom `use*` methods, which do not have access to the JSX. +Events are case sensitive. + ```typescript useOnWindow: (event: T | T[], eventQrl: EventQRL) => void ``` diff --git a/packages/qwik/src/core/tests/render-api.spec.tsx b/packages/qwik/src/core/tests/render-api.spec.tsx index 8d48387dffa..a16b8f7da5e 100644 --- a/packages/qwik/src/core/tests/render-api.spec.tsx +++ b/packages/qwik/src/core/tests/render-api.spec.tsx @@ -445,6 +445,28 @@ describe('render api', () => { '(window.qwikevents||(window.qwikevents=[]))' ); }); + it('should only render inside body', async () => { + const bigText = 'hello world '.repeat(4000); + const result = await renderToStringAndSetPlatform( + <> + + + + + +
{bigText}
+ + , + { + containerTagName: 'html', + qwikLoader: 'inline', + } + ); + const document = createDocument({ html: result.html }); + const qwikLoaderScriptElements = document.querySelectorAll('script[id=qwikloader]'); + expect(qwikLoaderScriptElements).toHaveLength(1); + expect(qwikLoaderScriptElements[0]?.parentNode?.nodeName.toLowerCase()).toEqual('body'); + }); it('should not render inside template', async () => { const bigText = 'hello world '.repeat(3000); // ~30kB of text const result = await renderToStringAndSetPlatform( diff --git a/packages/qwik/src/server/ssr-container.ts b/packages/qwik/src/server/ssr-container.ts index b0ade51e8b4..f25fb424c40 100644 --- a/packages/qwik/src/server/ssr-container.ts +++ b/packages/qwik/src/server/ssr-container.ts @@ -348,6 +348,8 @@ class SSRContainer extends _SharedContainer implements ISSRContainer { openContainer() { if (this.tag == 'html') { this.write(''); + // -1 so we only emit inside body + this.$noScriptHere$ = -1; } const containerAttributes = this.renderOptions.containerAttributes || {}; @@ -379,7 +381,8 @@ class SSRContainer extends _SharedContainer implements ISSRContainer { return this.closeElement(); } - private $noScriptHere$ = 0; + // -1 so we only emit inside body + private $noScriptHere$: number = 0; /** Renders opening tag for DOM element */ openElement( @@ -393,8 +396,8 @@ class SSRContainer extends _SharedContainer implements ISSRContainer { // We waited long enough, on slow connections the page is already partially visible this.emitQwikLoaderInline(); } - // keep track of noscript and template - else if (elementName === 'noscript' || elementName === 'template') { + // keep track of noscript and template, and for html we only emit inside body + else if (elementName === 'noscript' || elementName === 'template' || elementName === 'body') { this.$noScriptHere$++; } }