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

[6.x] 🚀 Welcoming the Foundry release! #430

Closed
jsamr opened this issue Nov 20, 2020 · 46 comments
Closed

[6.x] 🚀 Welcoming the Foundry release! #430

jsamr opened this issue Nov 20, 2020 · 46 comments
Labels
release Discuss a new release.

Comments

@jsamr
Copy link
Collaborator

jsamr commented Nov 20, 2020

Foundry Status

Check the PR!

⚠️ This post will be updated on a regular basis! First pre-release has been released in late November. As long as the README is not ready, development is occurring in the dev/foundry branch. Also note that the Foundry Playground app is versioned and regularly updated!

ℹ️ If you have ideas, suggestions or you dislike something in this pre-release, you're invited to comment in this thread: What do you dislike or believe is missing in Foundry?

ℹ️ If you'd like to report a bug, you can comment in this thread or ping us in our Discord channel.

Hello community! I have been working on the new "Foundry" release for a while now, and I have just published a demo on expo, "Foundry Playground", where you can experiment with the new engine and its features. Please give us feedback!

Testing Foundry Playground

  1. Download the expo app on your smartphone (iOS, Android).
  2. Play with the demo:

Trying Foundry

From Scratch

Be careful, a lot of breaking changes! A compat module will be released to ease the transition.

npm install --save react-native-render-html@foundry

Take a look at how to use the new renderer API here: #434 (comment) (section "Renderer API") or take inspiration from the demo snippets.

From the Playground

Clone

Clone this repository, "dev/foundry" branch:

git clone https://github.com/archriss/react-native-render-html.git --branch dev/foundry
cd react-native-render-html

Install

yarn install

Build

yarn build

Start the Playground App

yarn start

Test HTML Snippets on your own!

Play with demo/snippets/test.tsx and change the html variable.

A New Render Engine and CSS Processor

The new release should be significantly more reliable regarding styles and compliance with CSS / HTML standards. I have extracted two packages for this purpose:

  • @native-html/css-processor, which handles all the logic of translating CSS styles into native styles ;
  • @native-html/transient-render-engine, which implements RFC002 and is in charge of creating a data structure ready for rendering.

Both packages are available in the @native-html/core project monorepo. These packages are heavily tested against standards.

Features Highlight

See #434 (comment)

Demo

In the demo app, you can toggle the legacy (5.x) vs Foundry (6.x) modes with the L button below. You can inspect the HTML source, and even the Transient Render Tree structure. Try out the demo here.

Foundry / Legacy Modes HTML Source / Transient Render Tree


And a few extra screenshots

Drawer Menu Images

Progress

Check the "Remaining Work" section here: #434

Credits

Kudos to Expensify company which has hired me to work on the white space collapsing challenge, without which I would not have been able to commit full bandwidth those last 2 weeks! A great gift to the Open Source community. If you are an expert React Native contractor, they might have work for you (reactnative [at] expensify.com).

@M1ck0
Copy link

M1ck0 commented Dec 1, 2020

For some reason, iframe is not rendered at all. Youtube embed is inside iframe, and it is not loaded. Any ideas what could be the problem?
@jsamr

@jsamr

This comment has been minimized.

@M1ck0

This comment has been minimized.

@M1ck0

This comment has been minimized.

@jsamr
Copy link
Collaborator Author

jsamr commented Dec 1, 2020

@M1ck0

EDIT: Use @native-html/iframe-plugin

OLD ANSWER

You could write a custom renderer (it scales automatically to available screen width, given you provide contentWidth prop to the RenderHTML component). Example with this html:

<p>
<iframe width="560"
        height="315"
        src="https://www.youtube.com/embed/POK_Iw4m3fY"
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        allowfullscreen>
</iframe>
</p>

⚠️ Make sure you use the latest release (6.0.0-alpha.9) to gain access to useSharedProps hook!

Code Rendered
import React from 'react';
import {
  useSharedProps,
  defaultHTMLElementModels
} from 'react-native-render-html';
import WebView from 'react-native-webview';
import { SnippetDeclaration } from '../types';

function extractPrintDimensions({
  attrWidth,
  attrHeight,
  styleWidth,
  styleHeight,
  contentWidth
}) {
  let printWidth, printHeight;
  let ratio;
  if (typeof attrWidth === 'number' && typeof attrHeight === 'number') {
    ratio = attrWidth / attrHeight;
  } else if (
    typeof styleWidth === 'number' &&
    typeof styleHeight === 'number'
  ) {
    ratio = styleWidth / styleHeight;
  } else {
    ratio = 16 / 9;
  }
  printWidth = Math.min(
    contentWidth,
    typeof attrWidth === 'number'
      ? attrWidth
      : typeof styleWidth === 'number'
      ? styleWidth
      : contentWidth
  );
  printHeight = printWidth / ratio;
  return {
    printWidth,
    printHeight
  };
}

function IframeRenderer({ tnode, style, key }) {
  const { contentWidth } = useSharedProps();
  const { width, height, ...restStyle } = style;
  const attrWidth = Number(tnode.attributes.width);
  const attrHeight = Number(tnode.attributes.height);
  const { printWidth, printHeight } = extractPrintDimensions({
    attrWidth: Number.isNaN(attrWidth) ? null : attrWidth,
    attrHeight: Number.isNaN(attrHeight) ? null : attrHeight,
    styleWidth: width,
    styleHeight: height,
    contentWidth
  });
  const source = tnode.attributes.srcdoc
    ? { html: tnode.attributes.srcdoc }
    : { uri: tnode.attributes.src };
  return (
    <WebView
      key={key}
      source={source}
      style={{ ...restStyle, width: printWidth, height: printHeight }}
    />
  );
}

IframeRenderer.model = defaultHTMLElementModels.iframe;

const renderers = {
  iframe: IframeRenderer
}

Then, make sure you pass renderers as a prop to the RenderHTML component.

@jsamr jsamr changed the title 🚀 Welcoming the Foundry release! [6.x] 🚀 Welcoming the Foundry release! Dec 5, 2020
@brayanarrieta

This comment has been minimized.

@jsamr

This comment has been minimized.

@brayanarrieta

This comment has been minimized.

@jsamr
Copy link
Collaborator Author

jsamr commented Apr 13, 2021

For those of you who are interested in CSS counter styles (roman, arabic...), good news are reported here!

@adderly

This comment has been minimized.

@jsamr

This comment has been minimized.

@adderly

This comment has been minimized.

@jsamr

This comment has been minimized.

@nadav2051
Copy link

nadav2051 commented Apr 19, 2021

Hi! Thanks for the great job! not sure where to open bugs regarding Foundry issues, but I've tried to test the RTL with 6.0.24-alpha and it's not 100%,
My code:

return (<HTML
		source={{ html: this.props.htmlSource }}
		imagesMaxWidth={Dimensions.get('window').width}
		alterChildren={this.alterChildren.bind(this)}
		textSelectable
	        WebView={WebView}
	         renderersProps={{
	           ol: { enableExperimentalRtl: true },
	           ul: { enableExperimentalRtl: true }}}/>);

HTML Source:

<body>
                                    <p>English - bullets</p>
<p>&nbsp;</p>
<p style="text-align: center;">Center</p>
<ul style="text-align: center;">
<li dir="ltr">Hello</li>
<li dir="ltr">world</li>
</ul>
<p dir="ltr" style="text-align: center;">&nbsp;</p>
<p>&nbsp;</p>
<p>Left</p>
<ul>
<li>Hello</li>
<li>world</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p dir="rtl" style="text-align: right;">Right</p>
<ul dir="rtl" style="text-align: right;">
<li>Hello</li>
<li>world</li>
</ul>
<p dir="rtl" style="text-align: right;">&nbsp;</p>
                                </body>

react-native-render-html:
image

https://html-online.com/editor/:
image

@jsamr
Copy link
Collaborator Author

jsamr commented Apr 19, 2021

@nadav2051 It's totally appropriate to comment in this thread for Foundry bug reports! I however prefer snacks as it's very fast to reproduce. Also, it would be nice to add in which platform the bug appears. On my end, I didn't manage to reproduce the RTL issue neither on Android (10), nor on iOS (14.4). See the repro I used here: https://snack.expo.io/@jsamr/rnrh-alpha24-rtl-repro

As per the centering issue, worth investigating. I'll take a look.

@adderly
Copy link

adderly commented May 4, 2021

@adderly It's unlikely (though not impossible) that we have a hook misbehavior since the project is covered with the rules of hooks Eslint rules. The most likely causes are explained here. If however you're confident that the problem comes from this library, please share a reproduction in the form of a snack, or a git project.

You are correct @jsamr , i created a new project and it worked.

But in my current codebase it just doesn't work.

Solved it with this. I think it is related to react-native-web coming from expo.

facebook/react#13991 (comment)

@castalonirenz
Copy link

onLinkPress is not working on the foundry version.

im trying to console the function.

image

@jsamr
Copy link
Collaborator Author

jsamr commented May 18, 2021

@castalonirenz onLinkPress has been moved to renderersProps.a.onPress since version 6.0.0-alpha.23

@castalonirenz
Copy link

@jsamr Hi, only the attributes ref is being get from the props. How can i get the text that has been press by the user?

@jsamr
Copy link
Collaborator Author

jsamr commented May 18, 2021

@castalonirenz Not an obvious solution at the moment, although we could pass the TNode instead of attributes, so that you can freely inspect its children. Right now, you could mangle the dom via dom visitors, and setting a data-text attribute:

alpha.25

import { getText } from "domutils";

const domVisitors = {
  onElement(element) {
    if (element.tagName === "a") {
      element.attributes["data-text"] = getText(element);
    }
  },
};

alpha.24 and below

import { getText, isTag } from "domutils";

function alterDOMNode(node) {
  if (isTag(node) && node.tagName === "a") {
    node.attributes["data-text"] = getText(node);
  }
}

Now you will have a data-text attribute passed to your onPress callback.

@castalonirenz
Copy link

@castalonirenz Not an obvious solution at the moment, although we could pass the TNode instead of attributes, so that you can freely inspect its children. Right now, you could mangle the dom via dom visitors, and setting a data-text attribute:

alpha.25

import { getText } from "domutils";

const domVisitors = {
  onElement(element) {
    if (element.tagName === "a") {
      element.attributes["data-text"] = getText(element);
    }
  },
};

alpha.24 and below

import { getText, isTag } from "domutils";

function alterDOMNode(node) {
  if (isTag(node) && node.tagName === "a") {
    node.attributes["data-text"] = getText(node);
  }
}

Now you will have a data-text attribute passed to your onPress callback.

i will try this one and will give you an update in the next day. thanks for the reply appreciate it!

@castalonirenz
Copy link

@castalonirenz Not an obvious solution at the moment, although we could pass the TNode instead of attributes, so that you can freely inspect its children. Right now, you could mangle the dom via dom visitors, and setting a data-text attribute:

alpha.25

import { getText } from "domutils";

const domVisitors = {
  onElement(element) {
    if (element.tagName === "a") {
      element.attributes["data-text"] = getText(element);
    }
  },
};

alpha.24 and below

import { getText, isTag } from "domutils";

function alterDOMNode(node) {
  if (isTag(node) && node.tagName === "a") {
    node.attributes["data-text"] = getText(node);
  }
}

Now you will have a data-text attribute passed to your onPress callback.

this is working see my screenshot

image

Console:
image

@castalonirenz
Copy link

castalonirenz commented May 19, 2021

Is there anyway to implement numberOfLines in HTML? @jsamr thanks in advanced

@jsamr
Copy link
Collaborator Author

jsamr commented May 19, 2021

@castalonirenz See #243 (comment)

@jsamr
Copy link
Collaborator Author

jsamr commented Jun 4, 2021

@nadav2051 Regarding the centering issue, there is unfortunately nothing I can do since textAlign will only target Text elements, and the marker box where the counter is printed is wrapped in a View... consider this a "React Native barrier".

@jsamr
Copy link
Collaborator Author

jsamr commented Jun 8, 2021

Hi everyone! Good news, The Beta is out! Check this ticket.
I'm closing this thread; and I want to say a big thanks to anyone participating in the alpha ❤️.

@jsamr jsamr closed this as completed Jun 8, 2021
@jsamr jsamr unpinned this issue Jun 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release Discuss a new release.
Projects
None yet
Development

No branches or pull requests