An open API service indexing awesome lists of open source software.

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

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('');
```