Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
smmoosavi committed Nov 16, 2024
1 parent 5bca138 commit 9b62ab3
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 513 deletions.
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { render } from './render';
1 change: 1 addition & 0 deletions render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function render() {}
5 changes: 0 additions & 5 deletions src/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/lib/CData.tsx

This file was deleted.

7 changes: 0 additions & 7 deletions src/lib/Comment.tsx

This file was deleted.

7 changes: 0 additions & 7 deletions src/lib/Fragment.tsx

This file was deleted.

6 changes: 0 additions & 6 deletions src/lib/Ins.tsx

This file was deleted.

17 changes: 6 additions & 11 deletions src/lib/builtin.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import { type ReactElement } from 'react';

export const JsxXmlBuiltin = Symbol('JSXXML.Builtin');

export function isJsxXmlBuiltinElement(value: any) {
return value && value.$$typeof === JsxXmlBuiltin;
}
import { JsxXML, JsxXmlBuiltinElement } from './types';

export function createJsxXmlBuiltinElement(
type: string,
props: any,
): ReactElement {
children: any,
): JsxXmlBuiltinElement {
return {
// @ts-ignore
$$typeof: JsxXmlBuiltin,
$$typeof: JsxXML,
builtin: true,
type,
props,
key: null,
children,
};
}
14 changes: 14 additions & 0 deletions src/lib/react-builtin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ReactElement } from 'react';
import { createJsxXmlBuiltinElement } from './builtin';

export function createReactJsxXmlBuiltinElement(
type: string,
props: any,
children?: any,
): ReactElement {
return createJsxXmlBuiltinElement(
type,
props,
children,
) as any as ReactElement;
}
29 changes: 29 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const JsxXML = Symbol('JSXXML');
export type JsxXMLElement =
| JsxXmlComponentElement
| JsxXmlTagElement
| JsxXmlBuiltinElement;

export type JsxXmlBuiltinElement = {
$$typeof: typeof JsxXML;
builtin: true;
type: string;
props: any;
children: any;
};

export type JsxXmlTagElement = {
$$typeof: typeof JsxXML;
builtin: false;
type: string;
props: any;
children: any;
};

export type JsxXmlComponentElement = {
$$typeof: typeof JsxXML;
builtin: false;
type: (props: any) => JsxXMLElement;
props: any;
children: any;
};
89 changes: 4 additions & 85 deletions src/react.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,4 @@
import type { ReactElement } from 'react';
import { isFragment } from 'react-is';
import type { XMLBuilder } from 'xmlbuilder2/lib/interfaces';
import { isJsxXmlBuiltinElement } from './lib/builtin';

export function renderReactElement(cur: XMLBuilder, element: ReactElement) {
renderTag(cur, element);
return cur;
}

function renderTag(cur: XMLBuilder, element: ReactElement) {
if (isJsxXmlBuiltinElement(element)) {
renderBuiltinElement(cur, element);
return;
}
if (typeof element?.type === 'string') {
let el = cur.ele(element.type);
const attrs = mergeAttrs(
element.props,
element.key,
// @ts-ignore
element.ref,
);
renderAttrs(el, attrs);
renderChildren(el, element.props.children);
return;
}
if (typeof element?.type === 'function') {
if (element.type.prototype?.isReactComponent) {
throw new Error('Class components are not supported');
}
const attrs = mergeAttrs(
element.props,
element.key,
// @ts-ignore
element.ref,
);
// @ts-ignore
renderTag(cur, element.type(attrs));
}
if (isFragment(element)) {
renderChildren(cur, element.props.children);
}
}

function mergeAttrs(attrs: any, key: string | null, ref: string | null) {
return { key, ref, ...attrs };
}

function renderAttrs(cur: XMLBuilder, attrs: any) {
for (let key in attrs) {
if (key === 'children') {
continue;
}
cur.att(key, attrs[key]);
}
}

function renderChildren(cur: XMLBuilder, children: any) {
if (typeof children === 'string') {
cur.txt(children);
} else if (typeof children === 'number') {
cur.txt(children.toString());
} else if (Array.isArray(children)) {
children.forEach((child) => renderChildren(cur, child));
} else if (children) {
renderTag(cur, children);
}
}

export function renderBuiltinElement(cur: XMLBuilder, element: any) {
if (element.type === 'cdata') {
cur.dat(element.props.children);
}
if (element.type === 'comment') {
cur.com(element.props.children);
}
if (element.type === 'ins') {
cur.ins(element.props.target, element.props.content);
}
if (element.type === 'fragment') {
return renderChildren(cur, element.props.children);
}
return cur;
}
export { CData } from './react/CData';
export { Comment } from './react/Comment';
export { Fragment } from './react/Fragment';
export { Ins } from './react/Ins';
7 changes: 7 additions & 0 deletions src/react/CData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { joinTextChildren, TextChildren } from '../lib/join';
import { createReactJsxXmlBuiltinElement } from '../lib/react-builtin';

export function CData(props: { children: TextChildren }) {
const children = joinTextChildren(props.children);
return createReactJsxXmlBuiltinElement('cdata', {}, children);
}
7 changes: 7 additions & 0 deletions src/react/Comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { joinTextChildren, TextChildren } from '../lib/join';
import { createReactJsxXmlBuiltinElement } from '../lib/react-builtin';

export function Comment(props: { children: TextChildren }) {
const children = joinTextChildren(props.children);
return createReactJsxXmlBuiltinElement('comment', {}, children);
}
7 changes: 7 additions & 0 deletions src/react/Fragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ReactNode } from 'react';
import { createReactJsxXmlBuiltinElement } from '../lib/react-builtin';

export function Fragment(props: { children?: ReactNode }) {
const { children } = props;
return createReactJsxXmlBuiltinElement('fragment', {}, children);
}
6 changes: 6 additions & 0 deletions src/react/Ins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createReactJsxXmlBuiltinElement } from '../lib/react-builtin';

export function Ins(props: { target: string; content?: string }) {
const { target, content = '' } = props;
return createReactJsxXmlBuiltinElement('ins', { target, content });
}
Loading

0 comments on commit 9b62ab3

Please sign in to comment.