https://github.com/remorses/xmlize
Render XML using JSX, with support for context and async components
https://github.com/remorses/xmlize
Last synced: 3 months ago
JSON representation
Render XML using JSX, with support for context and async components
- Host: GitHub
- URL: https://github.com/remorses/xmlize
- Owner: remorses
- Created: 2025-03-03T17:02:13.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-03-03T18:02:16.000Z (10 months ago)
- Last Synced: 2025-09-29T07:28:18.051Z (3 months ago)
- Language: TypeScript
- Size: 382 KB
- Stars: 12
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# xmlize
Generate xml from jsx
## Install
```bash
npm install xmlize
# or
yarn add xmlize
# or
pnpm add xmlize
```
## Usage
```tsx
import { render } from 'xmlize';
import { expect } from 'vitest';
let xml = render().end({ headless: true });
expect(xml).toBe(``);
```
## TypeScript types support
You will need to update your `tsconfig.json` to use xmlize as the jsx runtime:
```json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "mlxize"
}
}
```
> `xmlize` also works with you don't define `jsxImportSource` but this way it will impossible to override typescript types for already existing HTML tags, this is because typescript will use the React types declarations if you don't pass a custom `jsxImportSource`.
You need to define which tags are available in JSX with:
```tsx
declare global {
// if you don't set jsxImportSource to xmlize you will also need to add `namespace React {` here, but you can't override native HTML tags this way.
namespace JSX {
interface ElementChildrenAttribute {
children?: any;
}
interface IntrinsicElements {
svg: {
width?: string | number;
height?: string | number;
viewBox?: string;
xmlns?: string;
version?: string;
preserveAspectRatio?: string;
children?: any;
};
rect: {
x?: string | number;
y?: string | number;
width?: string | number;
height?: string | number;
rx?: string | number;
ry?: string | number;
fill?: string;
stroke?: string;
strokeWidth?: string | number;
opacity?: string | number;
children?: any;
};
}
}
}
```
## API
### `render(jsx, options): XMLBuilder`
- `jsx`: JSX.Element
- `options`: [XMLBuilderCreateOptions](https://oozcitak.github.io/xmlbuilder2/builder-functions.html#builder-options)
The `render` function returns an instance of XMLBuilder. You can call the [end](https://oozcitak.github.io/xmlbuilder2/conversion-functions.html#end) to get the XML string.
### Components
You can define your own components by defining a function that returns a JSX.Element. Component name should start with a capital letter.
```tsx
import { render } from 'xmlize';
function MyComponent(props) {
return {props.children};
}
let xml = render().end({ headless: true });
```
## Async components
Async components are rendered concurrently, meaning if you have 4 components that sleep for 1 second each, renderAsync will return in 1 second only.
```tsx
import { renderAsync } from 'xmlize';
async function AsyncComponent(props) {
// Simulate async operation
const data = await fetchData();
return {props.children};
}
async function fetchData() {
await sleep(1000);
return 'async-data';
}
// Usage with renderAsync
const xml = await renderAsync(content);
expect(xml.end({ headless: true })).toBe(
'content',
);
```
## Context
You can use context to pass down props just like React, this works both with render and renderAsync.
```tsx
import { createContext, useContext } from 'xmlize';
import { render } from 'xmlize';
import { expect } from 'vitest';
// Create a context
const ThemeContext = createContext('light');
// Component that uses context
function ThemedComponent() {
const theme = useContext(ThemeContext);
return ;
}
// Provider component
function App() {
return (
);
}
// Usage
const xml = render().end({ headless: true });
expect(xml).toBe('');
// Default value is used when no provider is found
const xmlWithDefaultTheme = render().end({ headless: true });
expect(xmlWithDefaultTheme).toBe('');
```
### Built-in Components
```tsx
import { CData, Comment, Ins, Fragment } from 'xmlize';
import { render } from 'xmlize';
import { expect } from 'vitest';
// CData example
const value = 1;
let xml1 = render(
some text and {value}
,
).end({ headless: true });
expect(xml1).toBe('');
// Comment example
let xml2 = render(
some comment
,
).end({ headless: true });
expect(xml2).toBe('');
// Ins example
let xml3 = render(
,
).end({ headless: true });
expect(xml3).toBe('');
// Fragment example
let xml4 = render(
,
).end({ headless: true });
expect(xml4).toBe('');
```