Skip to content

Commit c8be767

Browse files
committed
doc: integration guide for external libs
1 parent dfe0a3b commit c8be767

9 files changed

+133
-49
lines changed

docs/docs/howto/intro.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Demo
44

5-
```tsx twoslash
5+
```jsx twoslash
66
// @errors: 2322
77

88
function MyComponent({ children }) {
@@ -103,7 +103,7 @@ Configure your `tsconfig.json` as follows:
103103

104104
If you don't have any other JSX runtimes like React or Preact set up, you can use
105105
`typed-htmx/typed-html`, which will convert JSX into strings at runtime.
106-
You can configure the runtime using [`jsxConfig`](/typed-htmx/docs/api/module.index/Variables/variable.jsxConfig-1):
106+
You can configure the runtime using [`jsxConfig`](/typed-htmx/docs/api/index/variables/jsxConfig):
107107

108108
```js twoslash
109109
import { jsxConfig } from "typed-htmx";

docs/docs/howto/xternal.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Augmenting external JSX libraries
2+
3+
typed-htmx is extremely minimal and requires the user to manually augment external JSX libraries that provide their own types.
4+
5+
## Common guidance
6+
7+
- Create a `types.d.ts` (any name is fine, as long as it ends in `.d.ts`) at the top of your src/ folder,
8+
or anywhere within the configured `include` of your tsconfig.json
9+
- Write a JSX element, e.g. `<div />`, and inspect its type
10+
- If you see React-related types, you are good to go
11+
- If not, try to discover the common namespace under which all HTML attributes go.
12+
13+
Let's use [Hono](https://hono.dev/top) as an example.
14+
15+
```tsx twoslash
16+
// @jsxImportSource: hono/jsx
17+
// In tsconfig.json, jsxImportSource = "hono/jsx"
18+
19+
// The type we are augmenting in this case is `Hono.HTMLAttributes`.
20+
// hx-boost is not recognized as a proper attribute yet.
21+
<div hx-boost="bogus" />
22+
//^?
23+
```
24+
25+
With this knowledge, we can now augment the type of `Hono.HTMLAttributes` assuming it is an interface:
26+
27+
```tsx twoslash
28+
// @errors: 2322
29+
// @jsxImportSource: hono/jsx
30+
/// <reference types="typed-htmx" />
31+
32+
declare global {
33+
namespace Hono {
34+
interface HTMLAttributes extends HtmxAttributes {}
35+
}
36+
}
37+
38+
<div hx-boost="bogus"
39+
style={{}}
40+
/>
41+
```
42+
43+
## Hono
44+
45+
```ts twoslash
46+
import 'typed-htmx';
47+
48+
declare global {
49+
namespace Hono {
50+
interface HTMLAttributes extends HtmxAttributes {}
51+
}
52+
}
53+
```
54+
55+
## Astro
56+
57+
```ts twoslash
58+
import 'typed-htmx';
59+
60+
declare global {
61+
namespace astroHTML.JSX {
62+
interface IntrinsicAttributes extends HtmxAttributes {}
63+
}
64+
}
65+
```

docs/docusaurus.config.js

+6-10
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ const config = {
2121
markdown: {
2222
format: 'md'
2323
},
24-
onBrokenLinks: "throw",
25-
onBrokenMarkdownLinks: "ignore",
24+
onBrokenLinks: "warn",
25+
onBrokenMarkdownLinks: "warn",
2626

2727
i18n: {
2828
defaultLocale: "en",
@@ -36,12 +36,10 @@ const config = {
3636
({
3737
entryPoints: ["../src/index.ts", "../src/jsx.d.ts"],
3838
tsconfig: "../tsconfig.json",
39-
readme: "none",
4039
hideInPageTOC: true,
40+
readme: 'none',
4141
watch: process.env.npm_lifecycle_event === "start",
42-
// cleanOutputDir: process.env.NODE_ENV !== 'production',
43-
cleanOutputDir: false,
44-
excludeExternals: true,
42+
cleanOutputDir: true,
4543
externalPattern: ["node_modules/**/*"],
4644
plugin: ["typedoc-plugin-mdn-links"],
4745
}),
@@ -70,19 +68,17 @@ const config = {
7068
defaultOptions: {
7169
noErrors: false,
7270
},
73-
/** @type {import('typescript').CompilerOptions} */
7471
defaultCompilerOptions: {
75-
types: ["typed-htmx"],
7672
jsx: 4, // react-jsx
77-
jsxImportSource: "typed-htmx/typed-html",
73+
jsxImportSource: 'typed-htmx/typed-html',
7874
target: 99, // esnext,
7975
strict: true,
76+
checkJs: true,
8077
noImplicitAny: false,
8178
module: 199, // nodenext,
8279
moduleResolution: 99, // nodenext
8380
},
8481
includeJSDocInHover: true,
85-
wrapFragments: true,
8682
alwayRaiseForTwoslashExceptions: true,
8783
disableImplicitReactImport: true,
8884
}),

docs/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
"clsx": "^1.2.1",
2222
"docusaurus-plugin-typedoc": "next",
2323
"docusaurus-preset-shiki-twoslash": "^1.1.41",
24+
"hono": "^3.11.12",
2425
"object-assign": "^4.1.1",
2526
"prism-react-renderer": "^1.3.5",
2627
"react": "^18.2.0",
2728
"react-dom": "^18.2.0",
28-
"rehype-raw": "^7.0.0",
2929
"typed-htmx": "link:..",
3030
"typedoc": "^0.25.6",
3131
"typedoc-plugin-markdown": "next",
@@ -34,8 +34,7 @@
3434
},
3535
"devDependencies": {
3636
"@docusaurus/module-type-aliases": "3.0.1",
37-
"@docusaurus/types": "^3.0.1",
38-
"remark-shiki-twoslash": "^3.1.3"
37+
"@docusaurus/types": "^3.0.1"
3938
},
4039
"browserslist": {
4140
"production": [

docs/pnpm-lock.yaml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/typedoc.json

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
{
2-
"categoryOrder": ["core", "*"]
2+
"$schema": "https://typedoc.org/schema.json",
3+
"categoryOrder": ["core", "*"],
4+
"sourceLinkExternal": true,
5+
"excludeExternals": true,
6+
"externalPattern": [
7+
"**/node_modules/**/*"
8+
],
9+
"readme": "bogus",
10+
"searchCategoryBoosts": {
11+
"Core": 2
12+
}
313
}

src/index.ts

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ function htmlTransformChildren(value: InterpValue): string {
9595
return out.join(" ");
9696
}
9797

98+
/**
99+
* A [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates)
100+
* that interprets different kinds of {@link InterpValue values} into escaped HTML.
101+
*
102+
* ```ts twoslash
103+
* import { html } from 'typed-htmx';
104+
* function assertEqual(left: any, right: any) {}
105+
* // ---cut---
106+
* const template = html`
107+
* <div hx-vals=${{ foo: 'bar' }} />
108+
* `;
109+
* assertEqual(template, `<div hx-vals='{"foo":"bar"}' />`);
110+
* ```
111+
*/
98112
export const html: HtmlTemplator = (raw, ...values) => {
99113
const values_ = values.map(htmlTransformChildren);
100114
return String.raw(raw, ...values_);

src/jsx.d.ts

+24-32
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,22 @@ type HxTriggerModifier =
4949
/**
5050
* An extensible directory of htmx extensions.
5151
*
52-
* ## Declaring a new extension
52+
* ### Declaring a new extension
5353
*
5454
* ```tsx twoslash
5555
* // in foo.d.ts:
5656
*
5757
* declare global {
58-
* namespace JSX {
59-
* interface HtmxExtensions {
60-
* myExtension: "my-extension";
61-
* }
62-
* interface HtmlTag {
63-
* /** Describe your attribute *\/
64-
* ["my-extension-attr"]?: string;
65-
* // Add any other attributes your extension uses here
66-
* }
67-
* }
58+
* namespace JSX {
59+
* interface HtmxExtensions {
60+
* myExtension: "my-extension";
61+
* }
62+
* interface HtmlTag {
63+
* /** Describe your attribute *\/
64+
* ["my-extension-attr"]?: string;
65+
* // Add any other attributes your extension uses here
66+
* }
67+
* }
6868
* }
6969
*
7070
* <div hx-ext="my-extension">
@@ -160,31 +160,24 @@ interface HtmxBuiltinExtensions {
160160
morphdom: "morphdom";
161161
}
162162

163-
/**
164-
* Variants of attributes also recognized by htmx.
165-
*/
166-
type HtmxData<T> = {
167-
[K in keyof T as K extends `hx-${string}` ? `data-${K}` : never]: T[K]
168-
}
169-
170163
/**
171164
* Definitions for htmx attributes up to 1.9.3.
172165
*/
173-
interface HtmxAttributes extends HtmxData<HtmxAttributes> {
166+
interface HtmxAttributes {
174167
/** @ignore For React compatibility only. */
175168
children?: {};
176169
/** @ignore For React compatibility only. */
177170
key?: {};
178171
/**
179172
* Issues a `GET` to the specified URL.
180173
* @see https://htmx.org/attributes/hx-get/
181-
* @category core
174+
* @category Core
182175
*/
183176
["hx-get"]?: string;
184177
/**
185178
* Issues a `POST` to the specified URL.
186179
* @see https://htmx.org/attributes/hx-post/
187-
* @category core
180+
* @category Core
188181
*/
189182
["hx-post"]?: string;
190183
/**
@@ -207,13 +200,13 @@ interface HtmxAttributes extends HtmxData<HtmxAttributes> {
207200
* for links and forms.
208201
*
209202
* @see https://htmx.org/attributes/hx-boost/
210-
* @category core
203+
* @category Core
211204
*/
212205
["hx-boost"]?: BoolStr;
213206
/**
214207
* Handle any event with a script inline.
215208
* @see https://htmx.org/attributes/hx-on/
216-
* @category core
209+
* @category Core
217210
* @remarks Event listeners on htmx-specific events need to be specified with a spread attribute, and
218211
* are otherwise not supported in vanilla JSX.
219212
* ```jsx
@@ -232,26 +225,26 @@ interface HtmxAttributes extends HtmxData<HtmxAttributes> {
232225
/**
233226
* Pushes the URL into the browser location bar, creating a new history entry.
234227
* @see https://htmx.org/attributes/hx-push-url/
235-
* @category core
228+
* @category Core
236229
*/
237230
["hx-push-url"]?: BoolStr | AnyStr;
238231
/**
239232
* Select content to swap in from a response.
240233
* @see https://htmx.org/attributes/hx-select/
241-
* @category core
234+
* @category Core
242235
*/
243236
["hx-select"]?: string;
244237
/**
245238
* Select content to swap in from a response, out of band (somewhere other than the target).
246239
* @see https://htmx.org/attributes/hx-select-oob/
247-
* @category core
240+
* @category Core
248241
*/
249242
["hx-select-oob"]?: string;
250243
/**
251244
* Controls how content is swapped in (`outerHTML`, `beforeend`, `afterend`, …).
252245
* @see https://htmx.org/attributes/hx-swap/
253-
* @see {@linkcode InsertPosition} which is used in [{@linkcode Element.insertAdjacentHTML}](https://developer.mozilla.org/docs/Web/API/Element/insertAdjacentHTML)
254-
* @category core
246+
* @see [`InsertPosition`](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML#position) which is used in `Element.insertAdjacentHTML`.
247+
* @category Core
255248
* @remarks
256249
* - `morph` swaps are part of the {@linkcode HtmxBuiltinExtensions.idiomorph idiomorph} extension.
257250
* - `morphdom` swaps are part of the {@linkcode HtmxBuiltinExtensions.morphdom morphdom} extension.
@@ -265,19 +258,19 @@ interface HtmxAttributes extends HtmxData<HtmxAttributes> {
265258
/**
266259
* Specifies the target element to be swapped.
267260
* @see https://htmx.org/attributes/hx-target/
268-
* @category core
261+
* @category Core
269262
*/
270263
["hx-target"]?: HxTarget | AnyStr;
271264
/**
272265
* Specifies the event that triggers the request.
273266
* @see https://htmx.org/attributes/hx-trigger/
274-
* @category core
267+
* @category Core
275268
*/
276269
["hx-trigger"]?: "every " | HxTriggerModifier | AnyStr;
277270
/**
278271
* Adds values to the parameters to submit with the request (JSON-formatted).
279272
* @see https://htmx.org/attributes/hx-params/
280-
* @category core
273+
* @category Core
281274
*/
282275
["hx-vals"]?: AnyStr | "javascript:" | "js:" | Record<PropertyKey, unknown>;
283276
/**
@@ -426,6 +419,5 @@ declare namespace JSX {
426419
interface HtmlTag extends HtmxAttributes {}
427420
}
428421

429-
// React (and other similar frameworks)
430422
/** @ignore */
431423
interface HTMLElement extends HtmxAttributes {}

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"include": ["./src/**/*"],
2+
"include": ["src/**/*"],
33
"compilerOptions": {
44
"target": "es2022",
55
"module": "commonjs",

0 commit comments

Comments
 (0)