From e035b02c9ec502ec2136b8e668942a9af14e10c9 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Thu, 12 Oct 2017 16:42:45 +0200 Subject: [PATCH 01/38] fix(HTMLStyles): properly apply tagsStyles to _constructStyles This means the custom renderers supplied in the module and eventually yours (if you are using the _constructStyles helper) will receive their styles from the tagsStyles prop --- src/HTMLStyles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTMLStyles.js b/src/HTMLStyles.js index 4be339646..57d38931c 100644 --- a/src/HTMLStyles.js +++ b/src/HTMLStyles.js @@ -32,7 +32,7 @@ export function _constructStyles ({ tagName, htmlAttribs, passProps, additionalS let defaultBlockStyles = generateDefaultBlockStyles(baseFontSize); return [ (styleSet === 'VIEW' ? defaultBlockStyles : defaultTextStyles)[tagName], - passProps.htmlStyles ? passProps.htmlStyles[tagName] : undefined, + passProps.tagsStyles ? passProps.tagsStyles[tagName] : undefined, _getElementClassStyles(htmlAttribs, passProps.classesStyles), htmlAttribs.style ? cssStringToRNStyle( From d39d54b3e7029ae49788f76c470d5176ae1663e9 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Thu, 12 Oct 2017 18:11:15 +0200 Subject: [PATCH 02/38] feat(HTML): add debug prop --- src/HTML.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/HTML.js b/src/HTML.js index 7bd7007b8..6ba24e501 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -14,6 +14,7 @@ export default class HTML extends PureComponent { ignoredTags: PropTypes.array.isRequired, ignoredStyles: PropTypes.array.isRequired, decodeEntities: PropTypes.bool.isRequired, + debug: PropTypes.bool.isRequired, ignoreNodesFunction: PropTypes.func, alterData: PropTypes.func, alterChildren: PropTypes.func, @@ -31,6 +32,7 @@ export default class HTML extends PureComponent { static defaultProps = { renderers: HTMLRenderers, + debug: false, decodeEntities: true, emSize: 14, baseFontSize: 14, @@ -337,7 +339,7 @@ export default class HTML extends PureComponent { } render () { - const { decodeEntities, customWrapper } = this.props; + const { decodeEntities, customWrapper, debug } = this.props; const { dom } = this.state; if (!dom) { return false; @@ -345,10 +347,12 @@ export default class HTML extends PureComponent { let RNNodes; const parser = new htmlparser2.Parser( new htmlparser2.DomHandler((_err, dom) => { - // console.log('DOMNodes', dom); - // console.log('Parsed nodes', this.mapDOMNodesTORNElements(dom)); const RNElements = this.mapDOMNodesTORNElements(dom); RNNodes = this.renderRNElements(RNElements); + if (debug) { + console.log('DOMNodes from htmlparser2', dom); + console.log('RNElements from render-html', RNElements); + } }), { decodeEntities: decodeEntities } ); From 60c42ecc2823e61a7eedc4c0a6c59ba5a95befc4 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Thu, 12 Oct 2017 18:11:36 +0200 Subject: [PATCH 03/38] feat(HTML): add listsPrefixesRenderers prop --- src/HTML.js | 10 ++++++++-- src/HTMLRenderers.js | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/HTML.js b/src/HTML.js index 6ba24e501..52083bf08 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -15,6 +15,7 @@ export default class HTML extends PureComponent { ignoredStyles: PropTypes.array.isRequired, decodeEntities: PropTypes.bool.isRequired, debug: PropTypes.bool.isRequired, + listsPrefixesRenderers: PropTypes.object, ignoreNodesFunction: PropTypes.func, alterData: PropTypes.func, alterChildren: PropTypes.func, @@ -214,7 +215,8 @@ export default class HTML extends PureComponent { return { wrapper: 'Text', data: data.replace(/(\r\n|\n|\r)/gm, ''), // remove linebreaks - attribs, parent, + attribs, + parent, tagName: name || 'rawtext' }; } @@ -275,7 +277,10 @@ export default class HTML extends PureComponent { * @memberof HTML */ renderRNElements (RNElements, parentWrapper = 'root', parentIndex = 0) { - const { tagsStyles, classesStyles, onLinkPress, imagesMaxWidth, emSize, ignoredStyles, baseFontSize } = this.props; + const { + tagsStyles, classesStyles, onLinkPress, imagesMaxWidth, emSize, ignoredStyles, baseFontSize, + listsPrefixesRenderers + } = this.props; return RNElements && RNElements.length ? RNElements.map((element, index) => { const { attribs, data, tagName, parent, parentTag, children, nodeIndex, wrapper } = element; const Wrapper = wrapper === 'Text' ? Text : View; @@ -310,6 +315,7 @@ export default class HTML extends PureComponent { emSize, baseFontSize, key, + listsPrefixesRenderers, rawChildren: children }); } diff --git a/src/HTMLRenderers.js b/src/HTMLRenderers.js index d2029f198..81a2cf406 100644 --- a/src/HTMLRenderers.js +++ b/src/HTMLRenderers.js @@ -48,13 +48,13 @@ export function img (htmlAttribs, children, convertedCSSStyles, passProps = {}) } export function ul (htmlAttribs, children, convertedCSSStyles, passProps = {}) { - const { rawChildren, nodeIndex, key, baseFontSize } = passProps; + const { rawChildren, nodeIndex, key, baseFontSize, listsPrefixesRenderers } = passProps; children = children && children.map((child, index) => { const rawChild = rawChildren[index]; let prefix = false; if (rawChild) { if (rawChild.parentTag === 'ul') { - prefix = ( + prefix = listsPrefixesRenderers && listsPrefixesRenderers.ul ? listsPrefixesRenderers.ul(...arguments) : ( ); } else if (rawChild.parentTag === 'ol') { - prefix = ( + prefix = listsPrefixesRenderers && listsPrefixesRenderers.ol ? listsPrefixesRenderers.ol(...arguments) : ( { index + 1 }) ); } From 24d1a5b8e9923aceb6bbea7b4a1ab0d92df83128 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Thu, 12 Oct 2017 18:13:28 +0200 Subject: [PATCH 04/38] fix(HTML): properly merge single child that don't need a wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a very important fix because in this snippet :
  • Zhang Kechun,Le Fleuve Jaune etGuillaume Millet,The Frontier
  • The content inside tags wouldn’t receive its styling before --- src/HTML.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTML.js b/src/HTML.js index 52083bf08..4887471a5 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -242,7 +242,7 @@ export default class HTML extends PureComponent { const firstChild = children && children[0]; if (firstChild && children.length === 1) { // Specific tweaks for wrappers with a single child - if (attribs === firstChild.attribs && + if ((attribs === firstChild.attribs || !firstChild.attribs) && firstChild.wrapper === wrapper && (tagName === firstChild.tagName || firstChild.tagName === 'rawtext')) { // If the only child of a node is using the same wrapper, merge them into one From 14445d4eaaf903fb731a5f21b65b85e4d0376014 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Thu, 12 Oct 2017 18:22:32 +0200 Subject: [PATCH 05/38] fix(HTML): break lines between title tags following themselves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This behavior was already implemented for the

    tag, let’s add a TEXT_TAGS_IGNORING_ASSOCIATION array holding all text tags that need to behave like this --- src/HTML.js | 7 +++---- src/HTMLUtils.js | 17 ++++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/HTML.js b/src/HTML.js index 4887471a5..b00cc2a3e 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -1,14 +1,13 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { View, Text, ViewPropTypes } from 'react-native'; -import { BLOCK_TAGS, TEXT_TAGS, IGNORED_TAGS, STYLESETS } from './HTMLUtils'; +import { BLOCK_TAGS, TEXT_TAGS, IGNORED_TAGS, TEXT_TAGS_IGNORING_ASSOCIATION, STYLESETS } from './HTMLUtils'; import { cssStringToRNStyle, _getElementClassStyles } from './HTMLStyles'; import { generateDefaultBlockStyles, generateDefaultTextStyles } from './HTMLDefaultStyles'; import htmlparser2 from 'htmlparser2'; import * as HTMLRenderers from './HTMLRenderers'; export default class HTML extends PureComponent { - static propTypes = { renderers: PropTypes.object.isRequired, ignoredTags: PropTypes.array.isRequired, @@ -144,14 +143,14 @@ export default class HTML extends PureComponent { associateRawTexts (children) { for (let i = 0; i < children.length; i++) { const child = children[i]; - if ((child.wrapper === 'Text' && child.tagName !== 'p') && children.length > 1 && (!child.parent || child.parent.name !== 'p')) { + if ((child.wrapper === 'Text' && TEXT_TAGS_IGNORING_ASSOCIATION.indexOf(child.tagName) === -1) && children.length > 1 && (!child.parent || child.parent.name !== 'p')) { // Texts outside

    or not

    themselves (with siblings) let wrappedTexts = []; for (let j = i; j < children.length; j++) { // Loop on its next siblings and store them in an array // until we encounter a block or a

    let nextSibling = children[j]; - if (nextSibling.wrapper !== 'Text' || nextSibling.tagName === 'p') { + if (nextSibling.wrapper !== 'Text' || TEXT_TAGS_IGNORING_ASSOCIATION.indexOf(nextSibling.tagName) === -1) { break; } wrappedTexts.push(nextSibling); diff --git a/src/HTMLUtils.js b/src/HTMLUtils.js index 9eda11119..5a30d81c2 100644 --- a/src/HTMLUtils.js +++ b/src/HTMLUtils.js @@ -3,17 +3,20 @@ import _RNViewStylePropTypes from 'react-native/Libraries/Components/View/ViewSt import _RNImageStylePropTypes from 'react-native/Libraries/Image/ImageStylePropTypes'; export const BLOCK_TAGS = ['address', 'article', 'aside', 'footer', 'hgroup', 'nav', 'section', 'blockquote', 'dd', 'div', -'dl', 'dt', 'figure', 'hr', 'li', 'main', 'ol', 'ul', 'cite', 'data', 'rp', 'rtc', 'ruby', 'area', -'img', 'map', 'center']; + 'dl', 'dt', 'figure', 'hr', 'li', 'main', 'ol', 'ul', 'cite', 'data', 'rp', 'rtc', 'ruby', 'area', + 'img', 'map', 'center']; export const TEXT_TAGS = ['a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'figcaption', 'p', 'pre', 'abbr', 'b', 'bdi', 'bdo', 'code', -'dfn', 'i', 'kbd', 'mark', 'q', 'rt', 's', 'samp', 'small', 'big', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr', -'del', 'ins', 'blink', 'font', 'em', 'bold', 'br']; + 'dfn', 'i', 'kbd', 'mark', 'q', 'rt', 's', 'samp', 'small', 'big', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr', + 'del', 'ins', 'blink', 'font', 'em', 'bold', 'br']; + +// These text tags shouldn't be associated with their siblings in the associateRawTags method +export const TEXT_TAGS_IGNORING_ASSOCIATION = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']; export const IGNORED_TAGS = ['head', 'scripts', 'audio', 'video', 'track', 'embed', 'object', 'param', 'source', 'canvas', 'noscript', -'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'button', 'datalist', 'fieldset', 'form', -'input', 'label', 'legend', 'meter', 'optgroup', 'option', 'output', 'progress', 'select', 'textarea', 'details', 'diaglog', -'menu', 'menuitem', 'summary']; + 'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'button', 'datalist', 'fieldset', 'form', + 'input', 'label', 'legend', 'meter', 'optgroup', 'option', 'output', 'progress', 'select', 'textarea', 'details', 'diaglog', + 'menu', 'menuitem', 'summary']; // As of react-native 0.48, this might change in the future export const PERC_SUPPORTED_STYLES = [ From e8ccd885f5b6fbf3cf8e04528146da577ad50d81 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 15:23:57 +0200 Subject: [PATCH 06/38] feat(HTMLImage): render alt if image cannot be displayed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mimicking browser’s rendering --- src/HTMLImage.js | 7 +++++-- src/HTMLRenderers.js | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/HTMLImage.js b/src/HTMLImage.js index 747731a1a..d29277dbb 100644 --- a/src/HTMLImage.js +++ b/src/HTMLImage.js @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { Image, View } from 'react-native'; +import { Image, View, Text } from 'react-native'; import PropTypes from 'prop-types'; const DEFAULT_WIDTH = 100; @@ -16,6 +16,7 @@ export default class HTMLImage extends PureComponent { static propTypes = { source: PropTypes.object.isRequired, + alt: PropTypes.string, style: Image.propTypes.style, imagesMaxWidth: PropTypes.number } @@ -77,7 +78,9 @@ export default class HTMLImage extends PureComponent { get errorImage () { return ( - + + { this.props.alt ? { this.props.alt } : false } + ); } diff --git a/src/HTMLRenderers.js b/src/HTMLRenderers.js index 81a2cf406..6c1044d69 100644 --- a/src/HTMLRenderers.js +++ b/src/HTMLRenderers.js @@ -43,7 +43,7 @@ export function img (htmlAttribs, children, convertedCSSStyles, passProps = {}) styleSet: 'IMAGE' }); return ( - + ); } From d7235791b26d63b58eaae1e7a0c055570d464dcc Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 15:24:27 +0200 Subject: [PATCH 07/38] fix(HTMLImage): don't overscale images with the imagesMaxWidth prop --- src/HTMLImage.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/HTMLImage.js b/src/HTMLImage.js index d29277dbb..f40462c81 100644 --- a/src/HTMLImage.js +++ b/src/HTMLImage.js @@ -53,12 +53,13 @@ export default class HTMLImage extends PureComponent { // Fetch image dimensions only if they aren't supplied or if with or height is missing Image.getSize( source.uri, - (width, height) => { - this.setState({ - width: imagesMaxWidth && width > imagesMaxWidth ? imagesMaxWidth : width, - height: imagesMaxWidth && width > imagesMaxWidth ? height / (width / imagesMaxWidth) : height, - error: false - }); + (originalWidth, originalHeight) => { + if (!imagesMaxWidth) { + return this.setState({ width: originalWidth, height: originalHeight }); + } + const optimalWidth = imagesMaxWidth <= originalWidth ? imagesMaxWidth : originalWidth; + const optimalHeight = (optimalWidth * originalHeight) / originalWidth; + this.setState({ width: optimalWidth, height: optimalHeight, error: false }); }, () => { this.setState({ error: true }); From 72d514862380cb316720a697fc4bb1070de225da Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:39:02 +0200 Subject: [PATCH 08/38] refactor(DefaultStyles): don't use the StyleSheet API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The StyleSheet.create method is problematic because of the caching logic of the style keys. We can’t make deep comparisons to properly apply some nested styles because of this. --- src/HTMLDefaultStyles.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HTMLDefaultStyles.js b/src/HTMLDefaultStyles.js index 33521d8dc..b1df263cd 100644 --- a/src/HTMLDefaultStyles.js +++ b/src/HTMLDefaultStyles.js @@ -27,7 +27,7 @@ export function generateDefaultBlockStyles (baseFontSize = BASE_FONT_SIZE) { } export function generateDefaultTextStyles (baseFontSize = BASE_FONT_SIZE) { - return StyleSheet.create({ + return { u: { textDecorationLine: 'underline' }, em: { fontStyle: 'italic' }, i: { fontStyle: 'italic' }, @@ -59,7 +59,7 @@ export function generateDefaultTextStyles (baseFontSize = BASE_FONT_SIZE) { marginTop: baseFontSize, marginBottom: baseFontSize } - }); + }; } /** From d03e69a4e00f286dfec45bc96e072551969906b3 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:40:32 +0200 Subject: [PATCH 09/38] feat(HTML): replace baseFontSize prop with baseFontStyle --- src/HTML.js | 64 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/src/HTML.js b/src/HTML.js index b00cc2a3e..573056db9 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -5,6 +5,7 @@ import { BLOCK_TAGS, TEXT_TAGS, IGNORED_TAGS, TEXT_TAGS_IGNORING_ASSOCIATION, ST import { cssStringToRNStyle, _getElementClassStyles } from './HTMLStyles'; import { generateDefaultBlockStyles, generateDefaultTextStyles } from './HTMLDefaultStyles'; import htmlparser2 from 'htmlparser2'; +import _isEqual from 'lodash.isequal'; import * as HTMLRenderers from './HTMLRenderers'; export default class HTML extends PureComponent { @@ -27,7 +28,7 @@ export default class HTML extends PureComponent { onLinkPress: PropTypes.func, imagesMaxWidth: PropTypes.number, emSize: PropTypes.number.isRequired, - baseFontSize: PropTypes.number.isRequired + baseFontStyle: PropTypes.object.isRequired } static defaultProps = { @@ -35,9 +36,9 @@ export default class HTML extends PureComponent { debug: false, decodeEntities: true, emSize: 14, - baseFontSize: 14, ignoredTags: IGNORED_TAGS, ignoredStyles: [], + baseFontStyle: { fontSize: 14 }, tagsStyles: {}, classesStyles: {} } @@ -59,7 +60,7 @@ export default class HTML extends PureComponent { } componentWillReceiveProps (nextProps) { - const { html, uri, ignoredTags, renderers, baseFontSize } = this.props; + const { html, uri, ignoredTags, renderers, baseFontStyle } = this.props; if (html !== nextProps.html || uri !== nextProps.uri) { this.imgsToRender = []; @@ -71,8 +72,8 @@ export default class HTML extends PureComponent { if (renderers !== nextProps.renderers) { this.renderers = { ...HTMLRenderers, ...(nextProps.renderers || {}) }; } - if (baseFontSize !== nextProps.baseFontSize) { - this.generateDefaultStyles(nextProps.baseFontSize); + if (!_isEqual(baseFontStyle, nextProps.baseFontStyle)) { + this.generateDefaultStyles(nextProps.baseFontStyle); } } @@ -95,24 +96,41 @@ export default class HTML extends PureComponent { } } - generateDefaultStyles (baseFontSize = this.props.baseFontSize) { - this.defaultBlockStyles = generateDefaultBlockStyles(baseFontSize); - this.defaultTextStyles = generateDefaultTextStyles(baseFontSize); + generateDefaultStyles (baseFontStyle = this.props.baseFontStyle) { + this.defaultBlockStyles = generateDefaultBlockStyles(baseFontStyle.fontSize || 14); + this.defaultTextStyles = generateDefaultTextStyles(baseFontStyle.fontSize || 14); } registerIgnoredTags (props = this.props) { this._ignoredTags = props.ignoredTags.map((tag) => tag.toLowerCase()); } - shouldApplyBaseFontSize (parent, classStyles) { - const { tagsStyles } = this.props; - const notOverridenByStyleAttribute = - !parent || !parent.attribs || !parent.attribs.style || (parent.attribs.style.search('font-size') === -1); - const notOverridenByTagsStyles = - !parent || !parent.name || !tagsStyles[parent.name] || !tagsStyles[parent.name]['fontSize']; - const notOverrideByClassesStyle = !classStyles || !classStyles['fontSize']; + filterBaseFontStyles (element, classStyles) { + const { tagsStyles, baseFontStyle } = this.props; + const { tagName, parentTag, parent, attribs } = element; + const styles = Object.keys(baseFontStyle); + let appliedStyles = {}; - return notOverridenByStyleAttribute && notOverridenByTagsStyles && notOverrideByClassesStyle; + for (let i = 0; i < styles.length; i++) { + const styleAttribute = styles[i]; + const styleAttributeWithCSSDashes = styleAttribute.replace(/[A-Z]/, (match) => { return `-${match.toLowerCase()}`; }); + const overridenFromStyle = attribs && attribs.style && attribs.style.search(styleAttributeWithCSSDashes) !== -1; + const overridenFromParentStyle = parent && parent.attribs && parent.attribs.style && parent.attribs.style.search(styleAttributeWithCSSDashes) !== -1; + + const overridenFromTagStyle = tagName && tagsStyles[tagName] && tagsStyles[tagName][styleAttribute]; + const overridenFromParentTagStyle = parentTag && tagsStyles[parentTag] && tagsStyles[parentTag][styleAttribute]; + + const overridenFromClassStyles = classStyles && classStyles[styleAttribute]; + + const notOverriden = !overridenFromStyle && !overridenFromParentStyle && + !overridenFromTagStyle && !overridenFromParentTagStyle && + !overridenFromClassStyles; + + if (notOverriden) { + appliedStyles[styleAttribute] = baseFontStyle[styleAttribute]; + } + } + return appliedStyles; } /** @@ -277,13 +295,13 @@ export default class HTML extends PureComponent { */ renderRNElements (RNElements, parentWrapper = 'root', parentIndex = 0) { const { - tagsStyles, classesStyles, onLinkPress, imagesMaxWidth, emSize, ignoredStyles, baseFontSize, + tagsStyles, classesStyles, onLinkPress, imagesMaxWidth, emSize, ignoredStyles, baseFontStyle, listsPrefixesRenderers } = this.props; return RNElements && RNElements.length ? RNElements.map((element, index) => { - const { attribs, data, tagName, parent, parentTag, children, nodeIndex, wrapper } = element; + const { attribs, data, tagName, parentTag, children, nodeIndex, wrapper } = element; const Wrapper = wrapper === 'Text' ? Text : View; - const key = `${wrapper}-${parentIndex}-${nodeIndex}-${index}`; + const key = `${wrapper}-${parentIndex}-${nodeIndex}-${tagName}-${index}-${parentTag}`; const convertedCSSStyles = attribs && attribs.style ? cssStringToRNStyle( @@ -311,19 +329,19 @@ export default class HTML extends PureComponent { imagesMaxWidth, parentTag, nodeIndex, + parentIndex, emSize, - baseFontSize, + baseFontStyle, key, + data, listsPrefixesRenderers, rawChildren: children }); } const classStyles = _getElementClassStyles(attribs, classesStyles); - // Base fontSize should be applied only if nothing else overrides it - const applyBaseFontSize = this.shouldApplyBaseFontSize(parent, classStyles); const textElement = data ? - { data } : + { data } : false; const style = [ From e76ab12341d65dac56c6b62eaafcab025bcd7254 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:41:24 +0200 Subject: [PATCH 10/38] fix(HTML): don't apply default styles for wrappers if you have set a style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So you don’t have to override the default styles by yourself --- src/HTML.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTML.js b/src/HTML.js index 573056db9..680267d2d 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -345,7 +345,7 @@ export default class HTML extends PureComponent { false; const style = [ - (Wrapper === Text ? this.defaultTextStyles : this.defaultBlockStyles)[tagName], + (!tagsStyles || !tagsStyles[tagName]) ? (Wrapper === Text ? this.defaultTextStyles : this.defaultBlockStyles)[tagName] : undefined, classStyles, tagsStyles ? tagsStyles[tagName] : undefined, convertedCSSStyles From 144892acc1138e4b2b5d9ed4ef3d3cb120ad7b36 Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:42:33 +0200 Subject: [PATCH 11/38] fix(HTML): properly filter out "raw" text tags that should be associated together This caused random line breaks in unintended places --- src/HTML.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HTML.js b/src/HTML.js index 680267d2d..90edca924 100644 --- a/src/HTML.js +++ b/src/HTML.js @@ -168,7 +168,7 @@ export default class HTML extends PureComponent { // Loop on its next siblings and store them in an array // until we encounter a block or a

    let nextSibling = children[j]; - if (nextSibling.wrapper !== 'Text' || TEXT_TAGS_IGNORING_ASSOCIATION.indexOf(nextSibling.tagName) === -1) { + if (nextSibling.wrapper !== 'Text' || TEXT_TAGS_IGNORING_ASSOCIATION.indexOf(nextSibling.tagName) !== -1) { break; } wrappedTexts.push(nextSibling); From 1669dc7c4cc574a1e9bb8c72468bd58f978a51ee Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:42:53 +0200 Subject: [PATCH 12/38] fix(HTMLRenderers): properly display raw text inside tags --- src/HTMLRenderers.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/HTMLRenderers.js b/src/HTMLRenderers.js index 6c1044d69..7b9995981 100644 --- a/src/HTMLRenderers.js +++ b/src/HTMLRenderers.js @@ -4,7 +4,7 @@ import { _constructStyles } from './HTMLStyles'; import HTMLImage from './HTMLImage'; export function a (htmlAttribs, children, convertedCSSStyles, passProps) { - const { parentWrapper, onLinkPress, key } = passProps; + const { parentWrapper, onLinkPress, key, data } = passProps; const style = _constructStyles({ tagName: 'a', htmlAttribs, @@ -19,13 +19,13 @@ export function a (htmlAttribs, children, convertedCSSStyles, passProps) { if (parentWrapper === 'Text') { return ( - { children } + { children || data } ); } else { return ( - { children } + { children || data } ); } From bce8d9e9946bd5174e28f18ae1c59396b4bf615d Mon Sep 17 00:00:00 2001 From: Maxime Bertonnier Date: Tue, 17 Oct 2017 17:45:14 +0200 Subject: [PATCH 13/38] fix(HTMLRenderers): apply fontSize from baseFontStyle to