Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀 Foundry release #434

Merged
merged 557 commits into from
Jun 8, 2021
Merged

🚀 Foundry release #434

merged 557 commits into from
Jun 8, 2021

Conversation

jsamr
Copy link
Collaborator

@jsamr jsamr commented Nov 26, 2020

Foundry Status

Check the announcement thread

Remaining work before stable release

Feature Parity (v4)

  • Support ignoredTags (renamed ignoredDomTags)
  • Support ignoreNodesFunction (renamed ignoreDomNode)
  • Support alterNode (moved to domVisitors.onElement, tamper directly the node reference and use domutils to insert, delete children)
  • Support alterChildren (moved to domVisitors.onElement, tamper with children via domutils)
  • Support alterData (moved to domVisitors.onText; tamper directly the node reference text field)
  • Support renderersProps
  • Support ignoredStyles (BREAKING: names should be camelCased.)
  • Support allowedStyles (BREAKING: names should be camelCased.)
  • Support emSize
  • Support nodeIndex and parent via tnode
  • Support an equivalent of listsPrefixesRendererscustomListStyleSpecs

Feature Parity (v5)

  • replace computeImagesMaxWidth with computeEmbeddedMaxWidth
  • support for htmlParserOptions
  • provide a podspec file
  • defaultTextProps
  • replace html and uri with source (supports method, body and headers)
  • WebView and defaultWebViewProps props
  • domNodeToHTMLString util

Fixes

New Features

  • Reuse special internal renderers logic (img, a, ul and ol) in custom renderers with useInternalRenderer.
  • Minimal renderer for tables. This renderer doesn't follow the CSS display: table, table-row and table-cell, because the display engine of react native only supports the flex display algorithm. To have a fully compliant table renderer, you can still use the @native-html/table-plugin package.
  • defaultViewProps
  • Access DocumentMetadata from any component (an object containing meta information of the document, such as lang, baseUrl, ...etc) with useDocumentMetadata hook, and from the controlling component with onDocumentMetadataLoaded prop.
  • Support baseUrl for RenderHTMLSourceInline sources
  • Provide URL normalization logic to users with DocumentMetadata. This helps normalize relative src and hrefs (useNormalizedUrl hook).
  • TRenderEngineProvider component to share one engine instance across multiple RenderHTML instances.
  • Implement the "marker model". Markers are special properties attached to a node which are inherited by all descendant nodes. For example, we could imagine adding blue borders to images which have an anchor parent. To check that we have an anchor parent, we will just need to test markers.anchor === true from the markers prop. You can also set custom markers with setMarkersForTNode prop.

Postponed

  • 🗙 90%+ branch test coverage → During beta testing
  • 🗙 Evaluate the cost of implementing CSS compliant "em" unit (current implementation doesn't follow the standard and is equivalent to rem).

Doc

  • Update README
  • (Maybe) create documentation website
  • New Discovery App (WIP) ; this enhanced demo app will also act as a guide to learn the fundamentals.
  • Migration guide

Tests

  • port all tests from v5
  • fix a handful of failing tests from v5

Modules

  • Extract iframe to a new package
  • Create a compatible release of @native-html/table-plugin
  • Create a compatible release of @native-html/iframe-plugin
  • 🗙 compat module to ease the transition cancelled in favor of migration guide

Fixes

Features Highlight

New props

  • idsStyles property (similar to classesStyles);
  • Support font selection (systemFonts and fallbackFonts props), see demo.
  • enableUserAgentStyles (true by default, the "browser" styles);
  • enableCSSInlineParsing (true by default)
  • enableExperimentalMarginCollapsing to comply with the margin collapsing CSS standard (experimental, only work on adjacent blocks, and doesn't work with percent units), see demo;
  • extendDefaultRenderer utility to tamper with the element model of a tag (see "Model Tampering" in the demo, which allows inline images!).
  • customListStyleSpecs to create arbitrary list counter styles.
  • renderersProps now supports renderer-specific fields. For example, renderersProps.a.onPress replaces onLinkPress prop.
  • renderersProps.(ol|ul).enableExperimentalRtl to reverse the display order of list markers and content when either dir attribute or direction CSS property are set to "rtl".

Elements

CSS

  • Complex style inheritance following closely CSS specificity;
  • White space collapsing! (Whitespace handling differs from HTML significantly (no collapsing, newlines ignored) #118) You can actually control this behavior (pre or normal) with a new special whiteSpace style property, or inline white-space: xx; see demo;
  • Support for the inline list-style-type CSS property! Also available in passed styles (tagsStyles...). Currently works with disc, circle, square, decimal, lower-alpha; upper-alpha. It currently only works with li and ul tags, see demo.
  • Extended support of special CSS units (e.g. 'thin' for border-width).
  • Extended support for basic CSS units (all absolute sizes such as pt, in, cm ... + ex).

Renderer API

  • Powerful new flexible API based on the transient render engine! ! Renderers are now components and not functions.
  • Custom renderers can easily reuse internal renderers, including children rendering logic. In addition to arguments that where available in the previous API, have access to the internal renderer component and props by using useInternalRenderer hook, to which you can pass ViewProps or TextProps, depending on the tnode, along with specific props for this renderer. This default renderer also supports onPress prop, so any renderer can be super easily configured as interactive!
  • Renderers are now bound to an element model, which characterizes how the element will be translated by the transient render engine (contentModel), what are the "user agent" styles for this tag (mixedUAStyles) and how to derive conditional user agent styles from attributes (getUADerivedStyleFromAttributes). There are some advanced options, such as isOpaque, which allows access to the children DOM tree from the TNode, especially useful for SVG and other special markups.
    Most of the time, you don't have to care about it, and just use the default model for this tag exported in defaultHTMLElementModels. It is yet a powerful feature which lets you put the hands on the engine!
  • Thanks to the separation between renderers and their content model, images can now be displayed inline (Support inline images #428)

Example of Custom Interactive

import React, { useCallback, useState } from 'react';
import {
  BlockRenderer,
  defaultHTMLElementModels,
  HTMLContentModel
} from 'react-native-render-html';
import { Text } from 'react-native';
import { Snackbar } from 'react-native-paper';

const ButtonRenderer: BlockRenderer = function ({
  TDefaultRenderer,
  ...props
}) {
  const [isVisible, setIsVisible] = useState(false);
  const onPress = useCallback(() => {
    setIsVisible(true);
  }, []);
  return (
    <>
      <TDefaultRenderer {...props} onPress={onPress} />
      <Snackbar
        duration={1200}
        visible={isVisible}
        onDismiss={() => setIsVisible(false)}>
        <Text>Button has been clicked!</Text>
      </Snackbar>
    </>
  );
};

// We need to extend the button HTMLElementModel because its
// default content model is HTMLContentModel.none. This is true
// for any interactive element.
ButtonRenderer.model = defaultHTMLElementModels.button.extend({
  contentModel: HTMLContentModel.block,
  mixedUAStyles: {
    textAlign: 'center',
    padding: 10,
    backgroundColor: 'rgba(125, 125, 125, 0.5)'
  }
});

const renderers = {
  button: ButtonRenderer
};

export default renderers;

Example of "Children Tampering"

Below is an example where our custom article render will inject advertisement below the second and fourth children:

import React from 'react';
import {
  BlockRenderer,
  defaultHTMLElementModels,
  useTNodeChildrenProps,
  TChildrenRenderer
} from 'react-native-render-html';
import { View, Text } from 'react-native';
import { SnippetDeclaration } from '../types';

const html = `
<article>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <p>Paragraph 3</p>
  <p>Paragraph 4</p>
  <p>Paragraph 5</p>
</article>`;

function AdComponent() {
  return (
    <View
      style={{ backgroundColor: 'purple', padding: 10, alignSelf: 'stretch' }}>
      <Text style={{ color: 'white' }}>I am an AD!</Text>
    </View>
  );
}

const ArticleRenderer: BlockRenderer = function ArticleRenderer(props) {
  const { tnode, TDefaultRenderer, ...defaultRendererProps } = props;
  const tchildrenProps = useTNodeChildrenProps(props);
  const firstChildrenChunk = tnode.children.slice(0, 2);
  const secondChildrenChunk = tnode.children.slice(2, 4);
  const thirdChildrenChunk = tnode.children.slice(4, 5);
  return (
    <TDefaultRenderer tnode={tnode} {...defaultRendererProps}>
      <TChildrenRenderer {...tchildrenProps} tchildren={firstChildrenChunk} />
      {firstChildrenChunk.length === 2 ? <AdComponent /> : null}
      <TChildrenRenderer {...tchildrenProps} tchildren={secondChildrenChunk} />
      {secondChildrenChunk.length === 2 ? <AdComponent /> : null}
      <TChildrenRenderer {...tchildrenProps} tchildren={thirdChildrenChunk} />
    </TDefaultRenderer>
  );
};

ArticleRenderer.model = defaultHTMLElementModels.article;

const renderers = {
  article: ArticleRenderer
}

export default renderers;

will render this html snippet:

<article>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <p>Paragraph 3</p>
  <p>Paragraph 4</p>
  <p>Paragraph 5</p>
</article>

like this

Removed props

  • customWrapper and containerStyle
  • onParsed
  • staticContentMaxWidth
  • ignoreNodesFunction
  • ptSize

@codecov-io
Copy link

codecov-io commented Nov 26, 2020

Codecov Report

Merging #434 (41f5ebc) into master (819e06e) will decrease coverage by 0.68%.
The diff coverage is 64.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #434      +/-   ##
==========================================
- Coverage   64.69%   64.00%   -0.69%     
==========================================
  Files           7       66      +59     
  Lines         473      614     +141     
  Branches      141      131      -10     
==========================================
+ Hits          306      393      +87     
- Misses         69      124      +55     
+ Partials       98       97       -1     
Impacted Files Coverage Δ
packages/render-html/src/GenericPressable.tsx 0.00% <0.00%> (ø)
...ender-html/src/elements/IMGElementContentError.tsx 0.00% <0.00%> (ø)
packages/render-html/src/elements/OLElement.tsx 0.00% <0.00%> (ø)
packages/render-html/src/elements/ULElement.tsx 0.00% <0.00%> (ø)
...es/render-html/src/render/extendDefaultRenderer.ts 0.00% <0.00%> (ø)
packages/render-html/src/UriSourceLoader.tsx 3.70% <3.70%> (ø)
...es/render-html/src/elements/GenericListElement.tsx 5.88% <5.88%> (ø)
...kages/render-html/src/hooks/useInternalRenderer.ts 16.66% <16.66%> (ø)
packages/render-html/src/renderers/OLRenderer.tsx 22.22% <22.22%> (ø)
packages/render-html/src/renderers/ULRenderer.tsx 22.22% <22.22%> (ø)
... and 122 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 819e06e...41f5ebc. Read the comment docs.

@jsamr jsamr force-pushed the dev/foundry branch 2 times, most recently from 852b62c to 5695fea Compare January 14, 2021 18:24
@bmanturner

This comment has been minimized.

@jsamr

This comment has been minimized.

@bmanturner

This comment has been minimized.

@jsamr

This comment has been minimized.

@bmanturner

This comment has been minimized.

@jsamr

This comment has been minimized.

@bmanturner

This comment has been minimized.

@jsamr

This comment has been minimized.

@jsamr jsamr changed the title 🚀 Foundry release (WIP) 🚀 Foundry release Jun 4, 2021
@jsamr jsamr merged commit a1c6748 into master Jun 8, 2021
@jsamr jsamr deleted the dev/foundry branch March 5, 2022 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment