1 | const React = require('react');
|
2 | const { StaticRouter } = require('react-router');
|
3 | const { renderToString, renderToStaticMarkup } = require('react-dom/server');
|
4 | const { renderRoutes, matchRoutes } = require('react-router-config');
|
5 | const { BrowserRouter, HashRouter } = require('react-router-dom');
|
6 | const { render } = require('react-dom');
|
7 |
|
8 | function isFunction(x) {
|
9 | return Object.prototype.toString.call(x) == '[object Function]';
|
10 | }
|
11 |
|
12 | function isString(input) {
|
13 | return (typeof input === "string") ? true : false;
|
14 | }
|
15 |
|
16 | function isObject(value) {
|
17 | if (Object.prototype.toString.call(value) !== '[object Object]') {
|
18 | return false
|
19 | } else {
|
20 | var prototype = Object.getPrototypeOf(value)
|
21 | return prototype === null || prototype === Object.prototype
|
22 | }
|
23 | }
|
24 |
|
25 | function isUndefined(x) {
|
26 | return !!(x === undefined);
|
27 | }
|
28 |
|
29 | function isNull(x) {
|
30 | return !!(x === null);
|
31 | }
|
32 |
|
33 | function isBoolean(value) {
|
34 | return !!(typeof value === 'boolean');
|
35 | }
|
36 |
|
37 | function isArray(o) {
|
38 | return !!o && typeof o === "object" && o.length !== undefined;
|
39 | }
|
40 |
|
41 | function isReactComponent(x) {
|
42 | return !!(x && objectHasValues(x) && ('$$typeof' in x) && (typeof x['$$typeof'] === 'symbol') && (x['$$typeof'].toString() === 'Symbol(react.element)'))
|
43 | }
|
44 |
|
45 | function objectHasValues(obj) {
|
46 | if (typeof obj === "object") {
|
47 | if (Object.getOwnPropertyNames(obj).length > 0) {
|
48 | return true;
|
49 | } else {
|
50 | return false;
|
51 | }
|
52 | } else if (typeof obj === 'undefined') {
|
53 | return false;
|
54 | }
|
55 | }
|
56 |
|
57 | function arrayHasValues(array) {
|
58 | if (array) {
|
59 | if (isArray(array)) {
|
60 | if (array.length) {
|
61 | return true
|
62 | } else {
|
63 | return false
|
64 | }
|
65 | } else {
|
66 | return false
|
67 | }
|
68 | } else {
|
69 | return false
|
70 | }
|
71 | }
|
72 |
|
73 | function avoidXSS(props) {
|
74 | return JSON.stringify(props).replace(/<\/script/g, '<\\/script').replace(/<!--/g, '<\\!--');
|
75 | }
|
76 |
|
77 | function resolveComponent(path) {
|
78 | let result;
|
79 | try {
|
80 | if (process.env.NODE_ENV !== "production") {
|
81 | delete require.cache[require.resolve(path)];
|
82 | }
|
83 | result = require(path).default;
|
84 | } catch (err) {
|
85 | result = false;
|
86 | } finally {
|
87 | return result;
|
88 | }
|
89 | }
|
90 |
|
91 | function renderComponent(location, component, props) {
|
92 | let Component;
|
93 |
|
94 | if (!component) {
|
95 | Component = React.createElement('div', null, null);
|
96 | if (process.env.NODE_ENV !== 'production') {
|
97 | console.info('The component you\'re trying to render seems to not exists.');
|
98 | }
|
99 | } else {
|
100 | Component = React.createElement(component, JSON.parse(avoidXSS(props.props)));
|
101 | }
|
102 |
|
103 | let context = {};
|
104 | let content = React.createElement(StaticRouter, { location, context }, Component);
|
105 |
|
106 | if (process.env.NODE_ENV === 'production') {
|
107 | return { html: renderToStaticMarkup(content), context: context };
|
108 | } else {
|
109 | return { html: renderToString(content), context: context };
|
110 | }
|
111 | }
|
112 |
|
113 | function getComponentByPathname(routes, path) {
|
114 | let route_ = null
|
115 |
|
116 | function get(_path, _routes) {
|
117 | _routes.some(route => {
|
118 | if ('path' in route && route.path === _path) {
|
119 | route_ = route
|
120 | return true
|
121 | } else {
|
122 | if ('routes' in route) {
|
123 | get(_path, route.routes)
|
124 | }
|
125 | return false
|
126 | }
|
127 | })
|
128 | }
|
129 |
|
130 | get(path, routes);
|
131 | return route_;
|
132 | }
|
133 |
|
134 | function getComponentFromRoutes(routes, url, props) {
|
135 | let extract = isBoolean(arguments[arguments.length -1]) ? arguments[arguments.length -1] : false;
|
136 | let output = { url, props, extract };
|
137 |
|
138 | if (arrayHasValues(routes)) {
|
139 | let branch = matchRoutes(routes, url);
|
140 | if (arrayHasValues(branch)) {
|
141 | if (extract) {
|
142 | if (objectHasValues(branch[0])) {
|
143 | if (objectHasValues(branch[0].route)) {
|
144 | if (objectHasValues(branch[0].route.component)) {
|
145 | if (isFunction(branch[0].route.component.default)) {
|
146 |
|
147 | output.Component = branch[0].route.component.default;
|
148 |
|
149 |
|
150 | if (objectHasValues(branch[1]) && objectHasValues(branch[1].match) && !branch[1].match.isExact) {
|
151 | let found = getComponentByPathname(routes, url);
|
152 | if (found && objectHasValues(found) && objectHasValues(found.component) && isFunction(found.component.default)) {
|
153 | output.Component = found.component.default;
|
154 | }
|
155 | }
|
156 | }
|
157 | } else if (isFunction(branch[0].route.component)) {
|
158 | output.Component = branch[0].route.component;
|
159 |
|
160 |
|
161 | if (objectHasValues(branch[1]) && objectHasValues(branch[1].match) && !branch[1].match.isExact) {
|
162 | let found = getComponentByPathname(routes, url);
|
163 | if (found && objectHasValues(found) && objectHasValues(found.component) && isFunction(found.component.default)) {
|
164 | output.Component = found.component.default;
|
165 | }
|
166 | }
|
167 | }
|
168 | }
|
169 | }
|
170 | } else {
|
171 | if (branch[0].route.component.default) {
|
172 | output.Component = branch[0].route.component.default;
|
173 | } else {
|
174 | output.Component = branch[0].route.component;
|
175 | }
|
176 | }
|
177 | } else {
|
178 | if (isArray(routes) && arrayHasValues(routes) && routes.length === 1) {
|
179 | if (isObject(routes[0]) && objectHasValues(routes[0])) {
|
180 | if (isFunction(routes[0].component)) {
|
181 | output.Component = routes[0].component
|
182 | }
|
183 | }
|
184 | }
|
185 | }
|
186 | }
|
187 |
|
188 | if (isBrowser()) {
|
189 | let Comp = output.Component;
|
190 | output.element = <Comp {...avoidXSS(props || {})} />
|
191 | //output.element = React.createElement(output.Component, JSON.parse(avoidXSS(props || {})));
|
192 | }
|
193 |
|
194 | return output;
|
195 | }
|
196 |
|
197 | function isBrowser() {
|
198 | return typeof window !== 'undefined';
|
199 | }
|
200 |
|
201 | function syncRouter(arrayRoutes, defaultComponent) {
|
202 | let properties = {};
|
203 | let component = null
|
204 |
|
205 | let router = window.__INITIAL_STATE__ && window.__INITIAL_STATE__.reactRouter;
|
206 |
|
207 | if (router) {
|
208 | let { url, props, extract } = window.__INITIAL_STATE__;
|
209 |
|
210 | // Get properties:
|
211 | if (isObject(props)) {
|
212 | properties = props;
|
213 | }
|
214 |
|
215 | // Get Component:
|
216 | if (arrayRoutes && isArray(arrayRoutes) && arrayHasValues(arrayRoutes) && isString(url)) {
|
217 | let { Component } = getComponentFromRoutes(arrayRoutes, url, properties, extract);
|
218 | component = Component;
|
219 | }
|
220 | }
|
221 |
|
222 | const output = {
|
223 | Router: window.location.origin.startsWith("file://") ? HashRouter : BrowserRouter,
|
224 | Component: component || defaultComponent || null,
|
225 | props: properties,
|
226 | refresh: !('pushState' in window.history),
|
227 | render: render,
|
228 | found: !!component
|
229 | };
|
230 |
|
231 | removeInitialState();
|
232 | disableLogHMR();
|
233 |
|
234 | if (isFunction(arguments[arguments.length -1])) {
|
235 | return arguments[arguments.length -1](output)
|
236 | } else {
|
237 | return output;
|
238 | }
|
239 | }
|
240 |
|
241 | function removeInitialState() {
|
242 | if (isBrowser()) {
|
243 | var parent = window.document.querySelector('head');
|
244 | var child = window.document.getElementById('__initial_state__');
|
245 | if (child) {
|
246 | parent.removeChild(child);
|
247 | }
|
248 | window.__INITIAL_STATE__ = null;
|
249 | }
|
250 | }
|
251 |
|
252 | function disableLogHMR() {
|
253 | if (isBrowser()) {
|
254 | if (process.env.NODE_ENV === 'development') {
|
255 | // This is a workaround used alongside the webpack-dev-server hot-module-reload feature
|
256 | // - it's quite chatty on the console, and there's no currently no configuration option
|
257 | // to silence it. Only used in development.
|
258 | // Prevent messages starting with [HMR] or [WDS] from being printed to the console
|
259 | (function(global) {
|
260 | let console_log = global.console.log
|
261 | global.console.log = function() {
|
262 | if (!(arguments.length == 1 && typeof arguments[0] === 'string' && arguments[0].match(/^\[(HMR|WDS)\]/))) {
|
263 | console_log.apply(global.console,arguments)
|
264 | }
|
265 | }
|
266 | // Credits to: https://github.com/webpack/webpack-dev-server/issues/109#issuecomment-143189783
|
267 | })(window)
|
268 | }
|
269 | }
|
270 | }
|
271 |
|
272 | module.exports.isFunction = isFunction;
|
273 | module.exports.isString = isString;
|
274 | module.exports.isObject = isObject;
|
275 | module.exports.isUndefined = isUndefined;
|
276 | module.exports.isNull = isNull;
|
277 | module.exports.isBoolean = isBoolean;
|
278 | module.exports.isArray = isArray;
|
279 | module.exports.isReactComponent = isReactComponent;
|
280 | module.exports.arrayHasValues = arrayHasValues;
|
281 | module.exports.objectHasValues = objectHasValues;
|
282 | module.exports.avoidXSS = avoidXSS;
|
283 | module.exports.resolveComponent = resolveComponent;
|
284 | module.exports.renderComponent = renderComponent;
|
285 | module.exports.getComponentByPathname = getComponentByPathname;
|
286 | module.exports.getComponentFromRoutes = getComponentFromRoutes;
|
287 | module.exports.isBrowser = isBrowser;
|
288 | module.exports.syncRouter = syncRouter;
|
289 | module.exports.removeInitialState = removeInitialState; |
\ | No newline at end of file |