UNPKG

8.78 kBJavaScriptView Raw
1const React = require('react');
2const { StaticRouter } = require('react-router');
3const { renderToString, renderToStaticMarkup } = require('react-dom/server');
4const { renderRoutes, matchRoutes } = require('react-router-config');
5const { BrowserRouter, HashRouter } = require('react-router-dom');
6const { render } = require('react-dom');
7
8function isFunction(x) {
9 return Object.prototype.toString.call(x) == '[object Function]';
10}
11
12function isString(input) {
13 return (typeof input === "string") ? true : false;
14}
15
16function 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
25function isUndefined(x) {
26 return !!(x === undefined);
27}
28
29function isNull(x) {
30 return !!(x === null);
31}
32
33function isBoolean(value) {
34 return !!(typeof value === 'boolean');
35}
36
37function isArray(o) {
38 return !!o && typeof o === "object" && o.length !== undefined;
39}
40
41function isReactComponent(x) {
42 return !!(x && objectHasValues(x) && ('$$typeof' in x) && (typeof x['$$typeof'] === 'symbol') && (x['$$typeof'].toString() === 'Symbol(react.element)'))
43}
44
45function 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
57function 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
73function avoidXSS(props) {
74 return JSON.stringify(props).replace(/<\/script/g, '<\\/script').replace(/<!--/g, '<\\!--');
75}
76
77function 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
91function 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
113function 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
134function 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 // Default component found:
147 output.Component = branch[0].route.component.default;
148
149 // Check if the component dont exists:
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 // Check if the component dont exists:
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
197function isBrowser() {
198 return typeof window !== 'undefined';
199}
200
201function 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
241function 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
252function 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
272module.exports.isFunction = isFunction;
273module.exports.isString = isString;
274module.exports.isObject = isObject;
275module.exports.isUndefined = isUndefined;
276module.exports.isNull = isNull;
277module.exports.isBoolean = isBoolean;
278module.exports.isArray = isArray;
279module.exports.isReactComponent = isReactComponent;
280module.exports.arrayHasValues = arrayHasValues;
281module.exports.objectHasValues = objectHasValues;
282module.exports.avoidXSS = avoidXSS;
283module.exports.resolveComponent = resolveComponent;
284module.exports.renderComponent = renderComponent;
285module.exports.getComponentByPathname = getComponentByPathname;
286module.exports.getComponentFromRoutes = getComponentFromRoutes;
287module.exports.isBrowser = isBrowser;
288module.exports.syncRouter = syncRouter;
289module.exports.removeInitialState = removeInitialState;
\No newline at end of file