|
@@ -2,119 +2,7 @@
|
2
|
2
|
|
3
|
3
|
import { Dimensions, Platform } from 'react-native';
|
4
|
4
|
|
5
|
|
-import Immutable from 'immutable';
|
6
|
|
-
|
7
|
|
-function appendFilesToHead(files, script) {
|
8
|
|
- return files.reduceRight((combinedScript, file) => {
|
9
|
|
- const { rel, type, href } = file;
|
10
|
|
- return `
|
11
|
|
- var link = document.createElement('link');
|
12
|
|
- link.rel = '${rel}';
|
13
|
|
- link.type = '${type}';
|
14
|
|
- link.href = '${href}';
|
15
|
|
- document.head.appendChild(link);
|
16
|
|
- ${combinedScript}
|
17
|
|
- `;
|
18
|
|
- }, script);
|
19
|
|
-}
|
20
|
|
-
|
21
|
|
-const screenWidth = Dimensions.get('window').width;
|
22
|
|
-
|
23
|
|
-const bodyStyle = `
|
24
|
|
-body {
|
25
|
|
- margin: 0;
|
26
|
|
- padding: 0;
|
27
|
|
-}
|
28
|
|
-`;
|
29
|
|
-
|
30
|
|
-function appendStylesToHead(styles, script) {
|
31
|
|
- const currentStyles = styles ? bodyStyle + styles : bodyStyle;
|
32
|
|
- // Escape any single quotes or newlines in the CSS with .replace()
|
33
|
|
- const escaped = currentStyles.replace(/\'/g, "\\'").replace(/\n/g, '\\n');
|
34
|
|
- return `
|
35
|
|
- var styleElement = document.createElement('style');
|
36
|
|
- styleElement.innerHTML = '${escaped}';
|
37
|
|
- document.head.appendChild(styleElement);
|
38
|
|
- ${script}
|
39
|
|
- `;
|
40
|
|
-}
|
41
|
|
-
|
42
|
|
-function getReloadRelatedData(props) {
|
43
|
|
- const { files, customStyle, customScript, style, source } = props;
|
44
|
|
- return {
|
45
|
|
- source,
|
46
|
|
- files,
|
47
|
|
- customStyle,
|
48
|
|
- customScript,
|
49
|
|
- style
|
50
|
|
- };
|
51
|
|
-}
|
52
|
|
-
|
53
|
|
-function isChanged(newValue, oldValue) {
|
54
|
|
- return !Immutable.is(Immutable.fromJS(newValue), Immutable.fromJS(oldValue));
|
55
|
|
-}
|
56
|
|
-
|
57
|
|
-function getInjectedSource(html, script) {
|
58
|
|
- return `
|
59
|
|
- ${html}
|
60
|
|
- <script>
|
61
|
|
- ${script}
|
62
|
|
- </script>
|
63
|
|
- `;
|
64
|
|
-}
|
65
|
|
-
|
66
|
|
-function getScript(props, getScript) {
|
67
|
|
- const { files, customStyle, customScript, style } = getReloadRelatedData(props);
|
68
|
|
- let script = getScript(style);
|
69
|
|
- script = files && files.length > 0 ? appendFilesToHead(files, script) : script;
|
70
|
|
- script = appendStylesToHead(customStyle, script);
|
71
|
|
- customScript && (script = customScript + script);
|
72
|
|
- return script;
|
73
|
|
-}
|
74
|
|
-
|
75
|
|
-export function getWidth(style) {
|
76
|
|
- return style && style.width ? style.width : screenWidth;
|
77
|
|
-}
|
78
|
|
-
|
79
|
|
-export function isEqual(newProps, oldProps) {
|
80
|
|
- return isChanged(getReloadRelatedData(newProps), getReloadRelatedData(oldProps));
|
81
|
|
-}
|
82
|
|
-
|
83
|
|
-export function setState(props, getBaseScript) {
|
84
|
|
- const { source, baseUrl } = props;
|
85
|
|
- const script = getScript(props, getBaseScript);
|
86
|
|
- let state = {};
|
87
|
|
- if (source.html) {
|
88
|
|
- let currentSource = { html: getInjectedSource(source.html, script) };
|
89
|
|
- baseUrl && Object.assign(currentSource, { baseUrl });
|
90
|
|
- Object.assign(state, { source: currentSource });
|
91
|
|
- } else {
|
92
|
|
- let currentSource = Object.assign({}, source);
|
93
|
|
- baseUrl && Object.assign(currentSource, { baseUrl });
|
94
|
|
- Object.assign(state, {
|
95
|
|
- source: currentSource,
|
96
|
|
- script
|
97
|
|
- });
|
98
|
|
- }
|
99
|
|
- return state;
|
100
|
|
-}
|
101
|
|
-
|
102
|
|
-export function handleSizeUpdated(height, width, onSizeUpdated) {
|
103
|
|
- onSizeUpdated &&
|
104
|
|
- onSizeUpdated({
|
105
|
|
- height,
|
106
|
|
- width
|
107
|
|
- });
|
108
|
|
-}
|
109
|
|
-
|
110
|
|
-export function isSizeChanged(height, oldHeight, width, oldWidth) {
|
111
|
|
- if (!height || !width) {
|
112
|
|
- return;
|
113
|
|
- }
|
114
|
|
- return height !== oldHeight || width !== oldWidth;
|
115
|
|
-}
|
116
|
|
-
|
117
|
|
-export const domMutationObserveScript = `
|
|
5
|
+const domMutationObserveScript = `
|
118
|
6
|
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
119
|
7
|
var observer = new MutationObserver(updateSize);
|
120
|
8
|
observer.observe(document, {
|
|
@@ -123,8 +11,8 @@ observer.observe(document, {
|
123
|
11
|
});
|
124
|
12
|
`;
|
125
|
13
|
|
126
|
|
-export function updateSizeWithMessage(element) {
|
127
|
|
- return `
|
|
14
|
+const updateSizeWithMessage = element =>
|
|
15
|
+ `
|
128
|
16
|
var updateSizeInterval = null;
|
129
|
17
|
var height = 0;
|
130
|
18
|
function updateSize(event) {
|
|
@@ -138,21 +26,6 @@ export function updateSizeWithMessage(element) {
|
138
|
26
|
window.ReactNativeWebView.postMessage(JSON.stringify({ width: width, height: height, event: event }));
|
139
|
27
|
}
|
140
|
28
|
`;
|
141
|
|
-}
|
142
|
|
-
|
143
|
|
-export function getStateFromProps(props, state) {
|
144
|
|
- const { height: oldHeight, width: oldWidth } = state;
|
145
|
|
- const height = props.style ? props.style.height : null;
|
146
|
|
- const width = props.style ? props.style.width : null;
|
147
|
|
- if (isSizeChanged(height, oldHeight, width, oldWidth)) {
|
148
|
|
- return {
|
149
|
|
- height: height || oldHeight,
|
150
|
|
- width: width || oldWidth,
|
151
|
|
- isSizeChanged: true
|
152
|
|
- };
|
153
|
|
- }
|
154
|
|
- return null;
|
155
|
|
-}
|
156
|
29
|
|
157
|
30
|
// add viewport setting to meta for WKWebView
|
158
|
31
|
const makeScalePageToFit = `
|
|
@@ -161,8 +34,8 @@ meta.setAttribute('name', 'viewport');
|
161
|
34
|
meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);
|
162
|
35
|
`;
|
163
|
36
|
|
164
|
|
-export function getBaseScript(style) {
|
165
|
|
- return `
|
|
37
|
+const getBaseScript = style =>
|
|
38
|
+ `
|
166
|
39
|
;
|
167
|
40
|
if (!document.getElementById("rnahw-wrapper")) {
|
168
|
41
|
var wrapper = document.createElement('div');
|
|
@@ -180,4 +53,86 @@ export function getBaseScript(style) {
|
180
|
53
|
${Platform.OS === 'ios' ? makeScalePageToFit : ''}
|
181
|
54
|
updateSize();
|
182
|
55
|
`;
|
|
56
|
+
|
|
57
|
+const appendFilesToHead = ({ files, script }) =>
|
|
58
|
+ files.reduceRight((combinedScript, file) => {
|
|
59
|
+ const { rel, type, href } = file;
|
|
60
|
+ return `
|
|
61
|
+ var link = document.createElement('link');
|
|
62
|
+ link.rel = '${rel}';
|
|
63
|
+ link.type = '${type}';
|
|
64
|
+ link.href = '${href}';
|
|
65
|
+ document.head.appendChild(link);
|
|
66
|
+ ${combinedScript}
|
|
67
|
+ `;
|
|
68
|
+ }, script);
|
|
69
|
+
|
|
70
|
+const screenWidth = Dimensions.get('window').width;
|
|
71
|
+
|
|
72
|
+const bodyStyle = `
|
|
73
|
+body {
|
|
74
|
+ margin: 0;
|
|
75
|
+ padding: 0;
|
183
|
76
|
}
|
|
77
|
+`;
|
|
78
|
+
|
|
79
|
+const appendStylesToHead = ({ style, script }) => {
|
|
80
|
+ const currentStyles = style ? bodyStyle + style : bodyStyle;
|
|
81
|
+ // Escape any single quotes or newlines in the CSS with .replace()
|
|
82
|
+ const escaped = currentStyles.replace(/\'/g, "\\'").replace(/\n/g, '\\n');
|
|
83
|
+ return `
|
|
84
|
+ var styleElement = document.createElement('style');
|
|
85
|
+ styleElement.innerHTML = '${escaped}';
|
|
86
|
+ document.head.appendChild(styleElement);
|
|
87
|
+ ${script}
|
|
88
|
+ `;
|
|
89
|
+};
|
|
90
|
+
|
|
91
|
+const getInjectedSource = ({ html, script }) => `
|
|
92
|
+${html}
|
|
93
|
+<script>
|
|
94
|
+${script}
|
|
95
|
+</script>
|
|
96
|
+`;
|
|
97
|
+
|
|
98
|
+const getScript = props => {
|
|
99
|
+ const { files, customStyle, customScript, style } = props;
|
|
100
|
+ let script = getBaseScript(style);
|
|
101
|
+ script = files && files.length > 0 ? appendFilesToHead({ files, script }) : script;
|
|
102
|
+ script = appendStylesToHead({ style: customStyle, script });
|
|
103
|
+ customScript && (script = customScript + script);
|
|
104
|
+ return script;
|
|
105
|
+};
|
|
106
|
+
|
|
107
|
+export const getWidth = style => {
|
|
108
|
+ return style && style.width ? style.width : screenWidth;
|
|
109
|
+};
|
|
110
|
+
|
|
111
|
+export const isSizeChanged = ({ height, previousHeight, width, previousWidth }) => {
|
|
112
|
+ if (!height || !width) {
|
|
113
|
+ return;
|
|
114
|
+ }
|
|
115
|
+ return height !== previousHeight || width !== previousWidth;
|
|
116
|
+}
|
|
117
|
+
|
|
118
|
+export const getMemoInputProps = props => {
|
|
119
|
+ const { files, customStyle, customScript, style, source, baseUrl } = props;
|
|
120
|
+ return [files, customStyle, customScript, style, source, baseUrl];
|
|
121
|
+};
|
|
122
|
+
|
|
123
|
+export const getMemoResult = props => {
|
|
124
|
+ const { source, baseUrl } = props;
|
|
125
|
+ const script = getScript(props);
|
|
126
|
+ if (source.html) {
|
|
127
|
+ let currentSource = { html: getInjectedSource({ html: source.html, script }) };
|
|
128
|
+ baseUrl && Object.assign(currentSource, { baseUrl });
|
|
129
|
+ return { source: currentSource };
|
|
130
|
+ } else {
|
|
131
|
+ let currentSource = Object.assign({}, source);
|
|
132
|
+ baseUrl && Object.assign(currentSource, { baseUrl });
|
|
133
|
+ return {
|
|
134
|
+ source: currentSource,
|
|
135
|
+ script
|
|
136
|
+ };
|
|
137
|
+ }
|
|
138
|
+};
|