Skip to content

Commit

Permalink
Merge pull request #28 from iamacup/text-style-fixes
Browse files Browse the repository at this point in the history
Text style fixes
  • Loading branch information
iamacup authored Nov 7, 2019
2 parents ae9740c + 57d7eb9 commit 51b07b7
Show file tree
Hide file tree
Showing 21 changed files with 287 additions and 111 deletions.
9 changes: 9 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
root: true,
extends: '@react-native-community',
settings: {
react: {
version: require('./package.json').peerDependencies.react,
},
}
};
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/node_modules
/.idea
package-lock.json
/.DS_Store
/.DS_Store
yarn-error.lock
yarn.lock
.eslintcache
7 changes: 0 additions & 7 deletions .prettierrc

This file was deleted.

6 changes: 6 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
};
16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
{
"name": "react-native-markdown-display",
"version": "4.0.2",
"version": "4.0.3",
"description": "Markdown renderer for react-native, with CommonMark spec support + adds syntax extensions & sugar (URL autolinking, typographer), originally created by Mient-jan Stelling as react-native-markdown-renderer",
"main": "src/index.js",
"types": "src/index.d.ts",
"scripts": {},
"scripts": {
"lint": "./node_modules/.bin/eslint --fix --cache ./src"
},
"pre-commit": [
"lint"
],
"repository": {
"type": "git",
"url": "git+https://github.com/iamacup/react-native-markdown-display.git"
Expand Down Expand Up @@ -36,6 +41,11 @@
},
"devDependencies": {
"chokidar": "^3.3.0",
"fs-extra": "^8.1.0"
"fs-extra": "^8.1.0",
"@babel/core": "^7.6.4",
"@babel/runtime": "^7.6.3",
"@react-native-community/eslint-config": "^0.0.5",
"eslint": "^6.6.0",
"pre-commit": "1.2.2"
}
}
39 changes: 26 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Base Markdown component
* @author Mient-jan Stelling
*/
import { useMemo } from 'react';
import {useMemo} from 'react';
import PropTypes from 'prop-types';
import parser from './lib/parser';
import applyStyle from './lib/util/applyStyle';
Expand All @@ -15,8 +15,8 @@ import AstRenderer from './lib/AstRenderer';
import MarkdownIt from 'markdown-it';
import PluginContainer from './lib/plugin/PluginContainer';
import blockPlugin from './lib/plugin/blockPlugin';
import { styles } from './lib/styles';
import { stringToTokens } from './lib/util/stringToTokens';
import {styles} from './lib/styles';
import {stringToTokens} from './lib/util/stringToTokens';
/**
*
*/
Expand Down Expand Up @@ -48,13 +48,13 @@ const getCopyFromChildren = children => {
const getRenderer = (renderer, rules, style, onLinkPress) => {
if (renderer && rules) {
console.warn(
'react-native-markdown-display you are using renderer and rules at the same time. This is not possible, props.rules is ignored'
'react-native-markdown-display you are using renderer and rules at the same time. This is not possible, props.rules is ignored',
);
}

if (renderer && style) {
console.warn(
'react-native-markdown-display you are using renderer and style at the same time. This is not possible, props.style is ignored'
'react-native-markdown-display you are using renderer and style at the same time. This is not possible, props.style is ignored',
);
}

Expand All @@ -63,7 +63,9 @@ const getRenderer = (renderer, rules, style, onLinkPress) => {
if (!(typeof renderer === 'function') || renderer instanceof AstRenderer) {
return renderer;
} else {
throw new Error('Provided renderer is not compatible with function or AstRenderer. please change');
throw new Error(
'Provided renderer is not compatible with function or AstRenderer. please change',
);
}
} else {
return new AstRenderer(
Expand All @@ -75,7 +77,7 @@ const getRenderer = (renderer, rules, style, onLinkPress) => {
...styles,
...style,
},
onLinkPress
onLinkPress,
);
}
};
Expand Down Expand Up @@ -105,8 +107,14 @@ const Markdown = ({
}),
onLinkPress = () => {},
}) => {
const momoizedRenderer = useMemo(() => getRenderer(renderer, rules, style, onLinkPress), [renderer, rules, style]);
const markdownParser = useMemo(() => getMarkdownParser(markdownit, plugins), [markdownit, plugins]);
const momoizedRenderer = useMemo(
() => getRenderer(renderer, rules, style, onLinkPress),
[onLinkPress, renderer, rules, style],
);
const markdownParser = useMemo(() => getMarkdownParser(markdownit, plugins), [
markdownit,
plugins,
]);

const copy = (this.copy = getCopyFromChildren(children));
return parser(copy, momoizedRenderer.render, markdownParser);
Expand All @@ -117,7 +125,10 @@ const Markdown = ({
*/
Markdown.propTypes = {
children: PropTypes.node.isRequired,
renderer: PropTypes.oneOfType([PropTypes.func, PropTypes.instanceOf(AstRenderer)]),
renderer: PropTypes.oneOfType([
PropTypes.func,
PropTypes.instanceOf(AstRenderer),
]),
onLinkPress: PropTypes.func,
rules: (props, propName, componentName) => {
let invalidProps = [];
Expand All @@ -128,17 +139,19 @@ Markdown.propTypes = {
}

if (typeof prop === 'object') {
invalidProps = Object.keys(prop).filter(key => typeof prop[key] !== 'function');
invalidProps = Object.keys(prop).filter(
key => typeof prop[key] !== 'function',
);
}

if (typeof prop !== 'object') {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. Must be of shape {[index:string]:function} `
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. Must be of shape {[index:string]:function} `,
);
} else if (invalidProps.length > 0) {
return new Error(
`Invalid prop \`${propName}\` supplied to \`${componentName}\`. These ` +
`props are not of type function \`${invalidProps.join(', ')}\` `
`props are not of type function \`${invalidProps.join(', ')}\` `,
);
}
},
Expand Down
62 changes: 53 additions & 9 deletions src/lib/AstRenderer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React, { Component, PropTypes } from "react";
import { Text, View } from "react-native";
import getUniqueID from "./util/getUniqueID";
import getUniqueID from './util/getUniqueID';

/**
*
Expand All @@ -15,6 +13,29 @@ export default class AstRenderer {
this._renderRules = renderRules;
this._style = style;
this._onLinkPress = onLinkPress;

// this is all the style props that are unique to <Text> components as of 07/Nov/2019
this._textStyleProps = [
'textShadowOffset',
'color',
'fontSize',
'fontStyle',
'fontWeight',
'lineHeight',
'textAlign',
'textDecorationLine',
'textShadowColor',
'fontFamily',
'textShadowRadius',
'includeFontPadding',
'textAlignVertical',
'fontVariant',
'letterSpacing',
'textDecorationColor',
'textDecorationStyle',
'textTransform',
'writingDirection',
];
}

/**
Expand All @@ -27,7 +48,7 @@ export default class AstRenderer {

if (!renderFunction) {
throw new Error(
`${type} renderRule not defined example: <Markdown rules={renderRules}>`
`${type} renderRule not defined example: <Markdown rules={renderRules}>`,
);
}
return renderFunction;
Expand All @@ -45,16 +66,39 @@ export default class AstRenderer {
const parents = [...parentNodes];
parents.unshift(node);

if (node.type === "text") {
return renderFunction(node, [], parentNodes, this._style);
if (node.type === 'text') {
// we build up a style object for text types, this effectively grabs the styles from parents and
// applies them in order of priority parent (most) to child (least) priority
// so that if we overwride the text style, it does not overwrite a header1 style, for instance.
const styleObj = {};

for (let a = 0; a < parentNodes.length; a++) {
if (this._style[parentNodes[a].type]) {
const arr = Object.keys(this._style[parentNodes[a].type]);

for (let b = 0; b < arr.length; b++) {
if (this._textStyleProps.includes(arr[b])) {
styleObj[arr[b]] = this._style[parentNodes[a].type][arr[b]];
}
}
}
}

return renderFunction(node, [], parentNodes, this._style, styleObj);
}

const children = node.children.map(value => {
return this.renderNode(value, parents);
});

if (node.type === "link" || node.type === "blocklink") {
return renderFunction(node, children, parentNodes, this._style, this._onLinkPress);
if (node.type === 'link' || node.type === 'blocklink') {
return renderFunction(
node,
children,
parentNodes,
this._style,
this._onLinkPress,
);
}

return renderFunction(node, children, parentNodes, this._style);
Expand All @@ -67,7 +111,7 @@ export default class AstRenderer {
*/
render = nodes => {
const children = nodes.map(value => this.renderNode(value, []));
const root = { type: "root", key: getUniqueID() };
const root = {type: 'root', key: getUniqueID()};
return this.getRenderFunction(root.type)(root, children, null, this._style);
};
}
4 changes: 2 additions & 2 deletions src/lib/data/PlatformEnum.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default {
IOS: "ios",
ANDROID: "android"
IOS: 'ios',
ANDROID: 'android',
};
6 changes: 2 additions & 4 deletions src/lib/parser.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react';
import { View } from 'react-native';
import tokensToAST from './util/tokensToAST';
import { stringToTokens } from './util/stringToTokens';
import { cleanupTokens } from './util/cleanupTokens';
import {stringToTokens} from './util/stringToTokens';
import {cleanupTokens} from './util/cleanupTokens';
import groupTextTokens from './util/groupTextTokens';

/**
Expand Down
Loading

0 comments on commit 51b07b7

Please sign in to comment.