Skip to content

Commit

Permalink
feat: new source type "RenderHTMLSourceDom" to render a DOM object
Browse files Browse the repository at this point in the history
  • Loading branch information
jsamr committed Jun 4, 2021
1 parent ade20ff commit eeec894
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 32 deletions.
2 changes: 1 addition & 1 deletion packages/render-html/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"dependencies": {
"@jsamr/counter-style": "^2.0.0",
"@jsamr/react-native-li": "^2.1.0",
"@native-html/transient-render-engine": "^8.1.2",
"@native-html/transient-render-engine": "^8.2.0",
"@types/ramda": "^0.27.40",
"@types/urijs": "^1.19.15",
"prop-types": "^15.5.7",
Expand Down
23 changes: 17 additions & 6 deletions packages/render-html/src/RenderHTMLSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import { Dimensions } from 'react-native';
import PropTypes from 'prop-types';
import ttreeEventsContext from './context/ttreeEventsContext';
import isUriSource from './helpers/isUriSource';
import InlineSourceLoader from './InlineSourceLoader';
import { SourceLoaderProps, TTreeEvents } from './internal-types';
import {
RenderHTMLSourceDom,
RenderHTMLSourceInline,
RenderHTMLSourceProps,
RenderHTMLSourceUri
} from './shared-types';
import UriSourceLoader from './UriSourceLoader';
import SourceLoaderUri from './SourceLoaderUri';
import SourceLoaderInline from './SourceLoaderInline';
import SourceLoaderDom from './SourceLoaderDom';
import debugMessage from './debugMessages';
import contentWidthContext from './context/contentWidthContext';
import isDomSource from './helpers/isDomSource';

export type RenderHTMLSourcePropTypes = Record<
keyof RenderHTMLSourceProps,
Expand All @@ -40,12 +43,17 @@ export const renderSourcePropTypes: RenderHTMLSourcePropTypes = {
};

function isEmptySource(
source: undefined | RenderHTMLSourceUri | RenderHTMLSourceInline
source:
| undefined
| RenderHTMLSourceUri
| RenderHTMLSourceInline
| RenderHTMLSourceDom
) {
return (
!source ||
(typeof (source as RenderHTMLSourceUri).uri !== 'string' &&
!(source as RenderHTMLSourceInline).html)
typeof (source as RenderHTMLSourceInline).html !== 'string' &&
!(source as RenderHTMLSourceDom).dom)
);
}

Expand All @@ -60,9 +68,12 @@ function RawSourceLoader({
return null;
}
if (isUriSource(source)) {
return React.createElement(UriSourceLoader, { source, ...props });
return React.createElement(SourceLoaderUri, { source, ...props });
}
return React.createElement(InlineSourceLoader, { source, ...props });
if (isDomSource(source)) {
return React.createElement(SourceLoaderDom, { source, ...props });
}
return React.createElement(SourceLoaderInline, { source, ...props });
}

const RenderHTMLSource = memo(
Expand Down
15 changes: 15 additions & 0 deletions packages/render-html/src/SourceLoaderDom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { SourceLoaderProps } from './internal-types';
import RenderTTree from './RenderTTree';
import { RenderHTMLSourceDom } from './shared-types';

export type DomSourceLoaderProps = {
source: RenderHTMLSourceDom;
} & SourceLoaderProps;

export default function SourceLoaderDom(props: DomSourceLoaderProps) {
return React.createElement(RenderTTree, {
document: props.source.dom,
baseUrl: props.source.baseUrl
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ function useInlineSourceLoader({
return source;
}

export default function InlineSourceLoader(props: InlineSourceLoaderProps) {
export default function SourceLoaderInline(props: InlineSourceLoaderProps) {
const { html } = useInlineSourceLoader(props);
return React.createElement(RenderTTree, {
html,
document: html,
baseUrl: props.source.baseUrl
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function useUriSourceLoader({ source, onHTMLLoaded }: UriSourceLoaderProps) {
return loadState;
}

export default function UriSourceLoader(props: UriSourceLoaderProps) {
export default function SourceLoaderUri(props: UriSourceLoaderProps) {
const { remoteErrorView, remoteLoadingView } = useContext(
sourceLoaderContext
);
Expand All @@ -87,7 +87,7 @@ export default function UriSourceLoader(props: UriSourceLoaderProps) {
return remoteLoadingView!.call(null, props.source);
}
return React.createElement(RenderTTree, {
html: resolvedHTML!,
document: resolvedHTML!,
baseUrl: props.source.uri
});
}
7 changes: 7 additions & 0 deletions packages/render-html/src/TRenderEngineProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ export const defaultTRenderEngineProviderProps: TransientRenderEngineConfig = {
triggerTREInvalidationPropNames: []
};

/**
* Use the ambient transient render engine.
*
* @returns The ambient transient render engine.
*
* @public
*/
export function useAmbientTRenderEngine() {
const engine = React.useContext(TRenderEngineContext);
if (__DEV__ && engine === defaultTRenderEngine) {
Expand Down
7 changes: 7 additions & 0 deletions packages/render-html/src/helpers/isDomSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RenderHTMLSource, RenderHTMLSourceDom } from '../shared-types';

export default function isDomSource(
source: RenderHTMLSource
): source is RenderHTMLSourceDom {
return 'dom' in source && typeof source.dom === 'object' && !!source.dom;
}
2 changes: 1 addition & 1 deletion packages/render-html/src/helpers/isUriSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { RenderHTMLSource, RenderHTMLSourceUri } from '../shared-types';
export default function isUriSource(
source: RenderHTMLSource
): source is RenderHTMLSourceUri {
return 'uri' in source;
return 'uri' in source && typeof source.uri === 'string';
}
28 changes: 18 additions & 10 deletions packages/render-html/src/hooks/useTTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,12 @@ import ttreeEventsContext from '../context/ttreeEventsContext';
import { useSharedProps } from '../context/SharedPropsProvider';
import { RenderTTreeProps } from '../internal-types';
import { useAmbientTRenderEngine } from '../TRenderEngineProvider';
import { TDocument } from '@native-html/transient-render-engine';

/**
* @internal
*/
export default function useTTree(props: RenderTTreeProps) {
const { html } = props;
function useTTreeChangeEffect(ttree: TDocument) {
const { onTTreeChange } = useContext(ttreeEventsContext);
const { debug } = useSharedProps();
const updateNumber = useRef(0);
const trenderEngine = useAmbientTRenderEngine();
const ttree = useMemo(() => trenderEngine.buildTTree(html), [
html,
trenderEngine
]);
useEffect(() => {
onTTreeChange?.call(null, ttree);
if (debug && __DEV__) {
Expand All @@ -30,5 +22,21 @@ export default function useTTree(props: RenderTTreeProps) {
);
}
}, [ttree, onTTreeChange, debug]);
}

/**
* @internal
*/
export default function useTTree(props: RenderTTreeProps) {
const { document } = props;
const trenderEngine = useAmbientTRenderEngine();
const ttree = useMemo(
() =>
typeof document === 'string'
? trenderEngine.buildTTree(document)
: trenderEngine.buildTTreeFromDoc(document),
[document, trenderEngine]
);
useTTreeChangeEffect(ttree);
return ttree;
}
4 changes: 3 additions & 1 deletion packages/render-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
DOMElement,
DOMNode,
DOMText,
DOMNodeWithChildren,
HTMLContentModel,
HTMLElementModel,
TRenderEngine
Expand Down Expand Up @@ -46,7 +47,8 @@ export {
export { default as TNodeRenderer } from './TNodeRenderer';
export {
default as TRenderEngineProvider,
defaultFallbackFonts
defaultFallbackFonts,
useAmbientTRenderEngine
} from './TRenderEngineProvider';
export { default as RenderHTMLConfigProvider } from './RenderHTMLConfigProvider';
export { default as RenderHTMLSource } from './RenderHTMLSource';
Expand Down
3 changes: 2 additions & 1 deletion packages/render-html/src/internal-types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DOMDocument, DOMElement } from '@native-html/transient-render-engine';
import { RenderHTMLProps } from './shared-types';

export type SourceLoaderProps = Pick<
Expand All @@ -6,7 +7,7 @@ export type SourceLoaderProps = Pick<
>;

export interface RenderTTreeProps {
html: string;
document: string | DOMElement | DOMDocument;
baseUrl?: string;
}

Expand Down
47 changes: 44 additions & 3 deletions packages/render-html/src/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import type {
HTMLContentModel,
CustomElementModel,
HTMLElementModel,
TRenderEngineOptions
TRenderEngineOptions,
DOMNodeWithChildren,
DOMElement,
DOMDocument
} from '@native-html/transient-render-engine';
import type { CounterStyleRenderer } from '@jsamr/counter-style';
import type { ComponentType, ReactElement, ReactNode } from 'react';
Expand Down Expand Up @@ -338,13 +341,23 @@ export interface TransientRenderEngineConfig {
/**
* Ignore specific DOM nodes.
*
* **Warning**: when this function is invoked, the node has not yet been
* attached to its parent or siblings. Use the second argument (`parent`)
* if you need to perform logic based on parent.
*
* @remarks
* - Use `ignoredDomTags` if you just need to target specific tag names.
* - The function is applied during DOM parsing, thus with very little
* overhead. However, it means that one node next siblings won't be
* available since it has not yet been parsed.
*
* @returns `true` if this node should not be included in the DOM, anything
* else otherwise.
*/
ignoreDomNode?: (node: DOMNode) => boolean;
ignoreDomNode?: (
node: DOMNode,
parent: DOMNodeWithChildren
) => boolean | void | unknown;
/**
* An object which callbacks will be invoked when a DOM element or text node
* has been parsed and its children attached. This is great to tamper the dom,
Expand Down Expand Up @@ -524,12 +537,40 @@ export interface RenderHTMLSourceInline {
baseUrl?: string;
}

/**
* A source which content is a DOM tree created by the transient render
* engine `parseDocument` method.
*
* See {@link useAmbientTRenderEngine}.
*
* @remarks When you use a DOM source, the `onHTMLLoaded` callback will never
* be invoked for this source, since the source loader hasn't access to the
* HTML source of the DOM.
*
* @public
*/
export interface RenderHTMLSourceDom {
/**
* A DOM object. This object **must** have been created with
* the transient render engine `parseDocument` method.
*/
dom: DOMElement | DOMDocument;
/**
* The base URL to resolve relative URLs in the HTML code.
* See {@link useNormalizedUrl}.
*/
baseUrl?: string;
}

/**
* The source to render.
*
* @public
*/
export type RenderHTMLSource = RenderHTMLSourceInline | RenderHTMLSourceUri;
export type RenderHTMLSource =
| RenderHTMLSourceInline
| RenderHTMLSourceDom
| RenderHTMLSourceUri;

/**
*
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4051,9 +4051,9 @@ __metadata:
languageName: node
linkType: hard

"@native-html/transient-render-engine@npm:^8.1.2":
version: 8.1.2
resolution: "@native-html/transient-render-engine@npm:8.1.2"
"@native-html/transient-render-engine@npm:^8.2.0":
version: 8.2.0
resolution: "@native-html/transient-render-engine@npm:8.2.0"
dependencies:
"@native-html/css-processor": 1.8.1
"@types/ramda": ^0.27.40
Expand All @@ -4065,7 +4065,7 @@ __metadata:
peerDependencies:
"@types/react-native": "*"
react-native: ^0.63.0
checksum: 23bfa7c9d3d2230305532059db8b090ff58fbb3790a892c06040179fcfc7a6c89af2886a4009e1529e51c53c0a5cd22f97071fcc3ce5647ff4b2b668c6ed6263
checksum: 0e72f1f857a3998af45855eca3112bf028fef2ad9cd5aba98c368b4f24cdb548ca7d45c718bd006b43fc4901940abc4cd8d84d435042540ff261edbe6d719305
languageName: node
linkType: hard

Expand Down Expand Up @@ -20271,7 +20271,7 @@ fsevents@^1.2.7:
"@jsamr/counter-style": ^2.0.0
"@jsamr/react-native-li": ^2.1.0
"@microsoft/api-extractor": ^7.14.0
"@native-html/transient-render-engine": ^8.1.2
"@native-html/transient-render-engine": ^8.2.0
"@release-it/conventional-changelog": ^2.0.1
"@testing-library/react-hooks": ^5.1.2
"@types/jest": ^26.0.23
Expand Down

0 comments on commit eeec894

Please sign in to comment.