This commit is contained in:
Thibault Malbranche 2018-11-26 15:30:06 +01:00
parent 2072aac5ee
commit 2e4cb88132
17 changed files with 2323 additions and 189 deletions

View File

@ -1,8 +1,8 @@
module.exports = {
// Airbnb is the base, prettier is here so that eslint doesn't conflict with prettier
extends: ['airbnb', 'prettier'],
parser: 'babel-eslint',
plugins: ['react', 'import'],
extends: ['airbnb-base', 'prettier', 'prettier/react'],
parser: 'typescript-eslint-parser',
plugins: ['react', 'react-native', 'typescript'],
rules: {
// Parens will be needed for arrow functions
'arrow-parens': ['error', 'as-needed', { requireForBlockBody: true }],
@ -14,7 +14,7 @@ module.exports = {
{ devDependencies: true, peerDependencies: true },
],
// Allows writing JSX in JS & TS files
// 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.ts'] }],
'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
// This rule doesn't play nice with Prettier
'react/jsx-one-expression-per-line': 'off',
// This rule doesn't play nice with Prettier
@ -22,34 +22,41 @@ module.exports = {
// Remove this rule because we only destructure props, but never state
'react/destructuring-assignment': 'off',
// Restrict imports that should be used carefully. Usually we have created a wrapper around them
'typescript/adjacent-overload-signatures': 'error',
'typescript/explicit-function-return-type': 'error',
'typescript/no-angle-bracket-type-assertion': 'error',
'typescript/no-empty-interface': 'error',
'typescript/no-explicit-any': 'error',
'typescript/no-inferrable-types': 'error',
'typescript/no-namespace': 'error',
'typescript/no-non-null-assertion': 'error',
'typescript/no-triple-slash-reference': 'error',
'typescript/no-type-alias': 'error',
'typescript/prefer-namespace-keyword': 'error',
'typescript/type-annotation-spacing': 'error',
'no-unused-vars': 'off',
},
overrides: [
{
files: ['*.ts', '*.tsx'],
files: ['*.ts?(x)'],
parser: 'typescript-eslint-parser',
plugins: ['react', 'import', 'typescript'],
rules: {
'typescript/adjacent-overload-signatures': 'error',
'typescript/explicit-function-return-type': 'error',
'typescript/no-angle-bracket-type-assertion': 'error',
'typescript/no-empty-interface': 'error',
'typescript/no-explicit-any': 'error',
'typescript/no-inferrable-types': 'error',
'typescript/no-namespace': 'error',
'typescript/no-non-null-assertion': 'error',
'typescript/no-triple-slash-reference': 'error',
'typescript/no-type-alias': 'error',
'typescript/prefer-namespace-keyword': 'error',
'typescript/type-annotation-spacing': 'error',
},
plugins: ['react', 'react-native', 'typescript'],
},
],
settings: {
'import/resolver': {
node: { extensions: ['.tsx', '.ts'] },
},
'import/cache:': {
lifetime: 2,
node: {
extensions: [
'.tsx',
'.ts',
'.android.tsx',
'.android.ts',
'.ios.tsx',
'.ios.ts',
],
},
},
},
};

View File

@ -1,8 +1,6 @@
// https://prettier.io/docs/en/options.html
module.exports = {
// Allow to parse .ts files and TS annotations
parser: 'typescript',
// Enables semicolons at the end of statements
semi: true,
// Formats strings with single quotes ('') instead of quotes ("")

21
.vscode/settings.json vendored
View File

@ -1,9 +1,22 @@
{
"prettier.disableLanguages": [
"json"
],
"files.associations": {
"*.test.js": "javascript",
"*.js": "javascriptreact",
"*.test.ts": "typescript",
"*.ts": "typescript",
"*.tsx": "typescriptreact"
},
"prettier.disableLanguages": ["json"],
"prettier.eslintIntegration": true,
"prettier.stylelintIntegration": true,
"prettier.singleQuote": true,
"prettier.trailingComma": "all",
"eslint.options": {
"extensions": [".js", ".ts", ".tsx"]
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
]
}

1
.yarnrc Normal file
View File

@ -0,0 +1 @@
save-exact true

View File

@ -1,3 +1,6 @@
import WebView from "./WebView";
import WebView from './src/WebView';
// We keep this for compatibility reasons.
export { WebView };
export default WebView;

View File

@ -8,6 +8,8 @@
* @flow
*/
/* eslint-disable */
'use strict';
import type {Node, Element, ComponentType} from 'react';

View File

@ -12,8 +12,10 @@
"homepage": "https://github.com/react-native-community/react-native-webview#readme",
"scripts": {
"ci:publish": "yarn semantic-release",
"ci:test": "yarn ci:test:tsc",
"ci:test:tsc": "yarn tsc --noEmit -p tsconfig.json",
"ci:test": "yarn ci:test:types && yarn ci:test:lint",
"ci:test:types": "yarn tsc",
"ci:test:lint": "yarn eslint . --max-warnings=0 --ext .js,.ts,.tsx",
"eslint-check": "eslint --print-config . | eslint-config-prettier-check",
"semantic-release": "semantic-release"
},
"peerDependencies": {
@ -27,16 +29,18 @@
"devDependencies": {
"@semantic-release/git": "7.0.5",
"@types/invariant": "^2.2.29",
"@types/react": "16.7.7",
"@types/react-native": "^0.57.6",
"eslint": "5.9.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-config-prettier": "3.3.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.11.1",
"eslint-plugin-react-native": "3.5.0",
"eslint-plugin-typescript": "0.13.0",
"prettier-eslint-cli": "4.7.1",
"eslint-plugin-typescript": "0.14.0",
"prettier-eslint-cli": "^4.7.1",
"react": "16.6.1",
"react-native": "0.57.5",
"semantic-release": "15.10.3",
"typescript": "3.1.6",
"typescript-eslint-parser": "21.0.1"

View File

@ -1,6 +1,5 @@
import React from 'react';
import ReactNative from 'react-native';
import {
ActivityIndicator,
StyleSheet,
@ -10,6 +9,7 @@ import {
NativeModules,
Image,
NativeSyntheticEvent,
findNodeHandle,
} from 'react-native';
import invariant from 'invariant';
@ -33,7 +33,7 @@ enum WebViewState {
ERROR = 'ERROR',
}
const defaultRenderLoading = () => (
const defaultRenderLoading = (): React.ReactNode => (
<View style={styles.loadingView}>
<ActivityIndicator style={styles.loadingProgressBar} />
</View>
@ -61,10 +61,9 @@ export default class WebView extends React.Component<
originWhitelist: WebViewShared.defaultOriginWhitelist,
};
static isFileUploadSupported = async () => {
static isFileUploadSupported = async (): Promise<boolean> =>
// native implementation should return "true" only for Android 5+
return NativeModules.RNCWebView.isFileUploadSupported();
};
NativeModules.RNCWebView.isFileUploadSupported();
state: State = {
viewState: this.props.startInLoadingState
@ -75,31 +74,34 @@ export default class WebView extends React.Component<
webViewRef = React.createRef<React.ComponentClass>();
render() {
render(): React.ReactNode {
let otherView = null;
if (this.state.viewState === WebViewState.LOADING) {
otherView = (this.props.renderLoading || defaultRenderLoading)();
} else if (this.state.viewState === WebViewState.ERROR) {
const errorEvent = this.state.lastErrorEvent;
invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
otherView =
this.props.renderError &&
this.props.renderError(
errorEvent!.domain,
errorEvent!.code,
errorEvent!.description,
);
if (errorEvent) {
otherView
= this.props.renderError
&& this.props.renderError(
errorEvent.domain,
errorEvent.code,
errorEvent.description,
);
} else {
invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
}
} else if (this.state.viewState !== WebViewState.IDLE) {
console.error(
'RNCWebView invalid state encountered: ' + this.state.viewState,
`RNCWebView invalid state encountered: ${this.state.viewState}`,
);
}
const webViewStyles = [styles.container, this.props.style];
if (
this.state.viewState === WebViewState.LOADING ||
this.state.viewState === WebViewState.ERROR
this.state.viewState === WebViewState.LOADING
|| this.state.viewState === WebViewState.ERROR
) {
// if we're in either LOADING or ERROR states, don't show the webView
webViewStyles.push(styles.hidden);
@ -128,7 +130,7 @@ export default class WebView extends React.Component<
WebViewShared.originWhitelistToRegex,
);
let NativeWebView = nativeConfig.component || RNCWebView;
const NativeWebView = nativeConfig.component || RNCWebView;
const webView = (
<NativeWebView
@ -246,9 +248,7 @@ export default class WebView extends React.Component<
}
};
getWebViewHandle = () => {
return ReactNative.findNodeHandle(this.webViewRef.current);
};
getWebViewHandle = () => findNodeHandle(this.webViewRef.current);
onLoadingStart = (event: WebViewNavigationEvent) => {
const onLoadStart = this.props.onLoadStart;

View File

@ -79,9 +79,9 @@ const defaultRenderError = (
) => (
<View style={styles.errorContainer}>
<Text style={styles.errorTextTitle}>Error loading page</Text>
<Text style={styles.errorText}>{'Domain: ' + errorDomain}</Text>
<Text style={styles.errorText}>{'Error Code: ' + errorCode}</Text>
<Text style={styles.errorText}>{'Description: ' + errorDesc}</Text>
<Text style={styles.errorText}>{`Domain: ${errorDomain}`}</Text>
<Text style={styles.errorText}>{`Error Code: ${errorCode}`}</Text>
<Text style={styles.errorText}>{`Description: ${errorDesc}`}</Text>
</View>
);
@ -112,6 +112,7 @@ export default class WebView extends React.Component<
State
> {
static JSNavigationScheme = JSNavigationScheme;
static NavigationType = NavigationType;
static defaultProps = {
@ -119,10 +120,9 @@ export default class WebView extends React.Component<
originWhitelist: WebViewShared.defaultOriginWhitelist,
};
static isFileUploadSupported = async () => {
static isFileUploadSupported = async () =>
// no native implementation for iOS, depends only on permissions
return true;
};
true;
state: State = {
viewState: this.props.startInLoadingState
@ -135,16 +135,16 @@ export default class WebView extends React.Component<
UNSAFE_componentWillMount() {
if (
this.props.useWebKit === true &&
this.props.scalesPageToFit !== undefined
this.props.useWebKit === true
&& this.props.scalesPageToFit !== undefined
) {
console.warn(
'The scalesPageToFit property is not supported when useWebKit = true',
);
}
if (
!this.props.useWebKit &&
this.props.allowsBackForwardNavigationGestures
!this.props.useWebKit
&& this.props.allowsBackForwardNavigationGestures
) {
console.warn(
'The allowsBackForwardNavigationGestures property is not supported when useWebKit = false',
@ -152,7 +152,7 @@ export default class WebView extends React.Component<
}
}
render() {
render(): React.ReactNode {
let otherView = null;
let scalesPageToFit;
@ -175,14 +175,14 @@ export default class WebView extends React.Component<
);
} else if (this.state.viewState !== WebViewState.IDLE) {
console.error(
'RNCWebView invalid state encountered: ' + this.state.viewState,
`RNCWebView invalid state encountered: ${this.state.viewState}`,
);
}
const webViewStyles = [styles.container, styles.webView, this.props.style];
if (
this.state.viewState === WebViewState.LOADING ||
this.state.viewState === WebViewState.ERROR
this.state.viewState === WebViewState.LOADING
|| this.state.viewState === WebViewState.ERROR
) {
// if we're in either LOADING or ERROR states, don't show the webView
webViewStyles.push(styles.hidden);
@ -216,9 +216,9 @@ export default class WebView extends React.Component<
Linking.openURL(url);
}
if (this.props.onShouldStartLoadWithRequest) {
shouldStart =
shouldStart &&
this.props.onShouldStartLoadWithRequest(event.nativeEvent);
shouldStart
= shouldStart
&& this.props.onShouldStartLoadWithRequest(event.nativeEvent);
}
invariant(viewManager != null, 'viewManager expected to be non-null');
viewManager.startLoadWithResult(
@ -392,9 +392,7 @@ export default class WebView extends React.Component<
/**
* Returns the native `WebView` node.
*/
getWebViewHandle = () => {
return findNodeHandle(this.webViewRef.current);
};
getWebViewHandle = () => findNodeHandle(this.webViewRef.current);
_onLoadingStart = (event: WebViewNavigationEvent) => {
const onLoadStart = this.props.onLoadStart;

View File

@ -1,4 +1,4 @@
const escapeStringRegexp = require('escape-string-regexp');
import escapeStringRegexp from 'escape-string-regexp';
const WebViewShared = {
defaultOriginWhitelist: ['http://*', 'https://*'],
@ -6,9 +6,8 @@ const WebViewShared = {
const result = /^[A-Za-z0-9]+:(\/\/)?[^/]*/.exec(url);
return result === null ? '' : result[0];
},
originWhitelistToRegex: (originWhitelist: string): string => {
return escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*');
},
originWhitelistToRegex: (originWhitelist: string): string =>
escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*'),
};
export default WebViewShared;

View File

@ -1,2 +1,2 @@
export * from './types/WebViewTypes'
export * from './WebView.ios'
export * from './types/WebViewTypes';
export * from './WebView.ios';

4
src/test.ts Normal file
View File

@ -0,0 +1,4 @@
const a
= 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
console.log(a);

12
src/test.tsx Normal file
View File

@ -0,0 +1,12 @@
import React from 'react';
const Test: React.SFC<{
show: boolean;
}> = ({ show }): React.ReactElement<string> => show && <div />;
const a =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
console.log(a);
export default Test;

View File

@ -68,8 +68,8 @@ export type WebViewMessageEvent = NativeSyntheticEvent<WebViewMessage>;
export type WebViewErrorEvent = NativeSyntheticEvent<WebViewError>;
export type DataDetectorTypes =
| 'phoneNumber'
export type DataDetectorTypes
= | 'phoneNumber'
| 'link'
| 'address'
| 'calendarEvent'

View File

@ -1,3 +1,4 @@
import { WebViewSourceUri } from "./types/WebViewTypes";
import { WebViewSourceUri } from './types/WebViewTypes';
export const isWebViewUriSource = (source: any): source is WebViewSourceUri =>
typeof source !== "number" && !("html" in source);
typeof source !== 'number' && !('html' in source);

View File

@ -3,27 +3,18 @@
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "react-native",
"lib": ["es6"],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"pretty": true,
"skipLibCheck": true,
"strict": true,
"strict": true
},
"include": [
"src",
"./typings.d.ts",
"types",
"test"
],
"exclude": [
"node_modules",
"dist"
]
}
"include": ["src", "./typings.d.ts", "types", "test"],
"exclude": ["node_modules"]
}

2275
yarn.lock

File diff suppressed because it is too large Load Diff