react-inlinesvg 0.7.1 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js ADDED
@@ -0,0 +1,225 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import httpplease from 'httpplease';
4
+ import ieXDomain from 'httpplease/plugins/oldiexdomain';
5
+
6
+ import {
7
+ configurationError,
8
+ isSupportedEnvironment,
9
+ randomString, uniquifySVGIDs,
10
+ unsupportedBrowserError,
11
+ } from './utils';
12
+
13
+ const http = httpplease.use(ieXDomain);
14
+
15
+ const Status = {
16
+ PENDING: 'pending',
17
+ LOADING: 'loading',
18
+ LOADED: 'loaded',
19
+ FAILED: 'failed',
20
+ UNSUPPORTED: 'unsupported'
21
+ };
22
+
23
+ const getRequestsByUrl = {};
24
+ const loadedIcons = {};
25
+
26
+ export default class InlineSVG extends React.PureComponent {
27
+ constructor(props) {
28
+ super(props);
29
+
30
+ this.state = {
31
+ status: Status.PENDING
32
+ };
33
+
34
+ this.isActive = false;
35
+ }
36
+
37
+ static propTypes = {
38
+ cacheGetRequests: PropTypes.bool,
39
+ children: PropTypes.node,
40
+ className: PropTypes.string,
41
+ onError: PropTypes.func,
42
+ onLoad: PropTypes.func,
43
+ preloader: PropTypes.node,
44
+ src: PropTypes.string.isRequired,
45
+ style: PropTypes.object,
46
+ supportTest: PropTypes.func,
47
+ uniqueHash: PropTypes.string,
48
+ uniquifyIDs: PropTypes.bool,
49
+ wrapper: PropTypes.func
50
+ };
51
+
52
+ static defaultProps = {
53
+ cacheGetRequests: false,
54
+ onLoad: () => {},
55
+ supportTest: isSupportedEnvironment,
56
+ uniquifyIDs: true,
57
+ wrapper: React.createFactory('span'),
58
+ };
59
+
60
+ componentWillMount() {
61
+ this.isActive = true;
62
+ }
63
+
64
+ componentDidMount() {
65
+ /* istanbul ignore else */
66
+ if (this.state.status === Status.PENDING) {
67
+ if (this.props.supportTest()) {
68
+ if (this.props.src) {
69
+ this.startLoad();
70
+ }
71
+ else {
72
+ this.fail(configurationError('Missing source'));
73
+ }
74
+ }
75
+ else {
76
+ this.fail(unsupportedBrowserError());
77
+ }
78
+ }
79
+ }
80
+
81
+ componentDidUpdate(prevProps) {
82
+ if (prevProps.src !== this.props.src) {
83
+ if (this.props.src) {
84
+ this.startLoad();
85
+ }
86
+ else {
87
+ this.fail(configurationError('Missing source'));
88
+ }
89
+ }
90
+ }
91
+
92
+ componentWillUnmount() {
93
+ this.isActive = false;
94
+ }
95
+
96
+ getFile(callback) {
97
+ const { cacheGetRequests, src } = this.props;
98
+
99
+ if (cacheGetRequests) {
100
+ if (loadedIcons[src]) {
101
+ const [err, res] = loadedIcons[src];
102
+
103
+ setTimeout(() => callback(err, res, true), 0);
104
+ }
105
+
106
+ if (!getRequestsByUrl[src]) {
107
+ getRequestsByUrl[src] = [];
108
+
109
+ http.get(src, (err, res) => {
110
+ getRequestsByUrl[src].forEach(cb => {
111
+ loadedIcons[src] = [err, res];
112
+ cb(err, res);
113
+ });
114
+ });
115
+ }
116
+
117
+ getRequestsByUrl[src].push(callback);
118
+ }
119
+ else {
120
+ http.get(src, (err, res) => {
121
+ callback(err, res);
122
+ });
123
+ }
124
+ }
125
+
126
+ fail(error) {
127
+ const status = error.isUnsupportedBrowserError ? Status.UNSUPPORTED : Status.FAILED;
128
+
129
+ /* istanbul ignore else */
130
+ if (this.isActive) {
131
+ this.setState({ status }, () => {
132
+ if (typeof this.props.onError === 'function') {
133
+ this.props.onError(error);
134
+ }
135
+ });
136
+ }
137
+ }
138
+
139
+ startLoad() {
140
+ /* istanbul ignore else */
141
+ if (this.isActive) {
142
+ this.setState({
143
+ status: Status.LOADING
144
+ }, this.load);
145
+ }
146
+ }
147
+
148
+ load() {
149
+ const match = this.props.src.match(/data:image\/svg[^,]*?(;base64)?,(.*)/);
150
+
151
+ if (match) {
152
+ return this.handleLoad(null, {
153
+ text: match[1] ? atob(match[2]) : decodeURIComponent(match[2])
154
+ });
155
+ }
156
+
157
+ return this.getFile(this.handleLoad);
158
+ }
159
+
160
+ handleLoad = (err, res, isCached = false) => {
161
+ if (err) {
162
+ this.fail(err);
163
+ return;
164
+ }
165
+
166
+ if (this.isActive) {
167
+ this.setState({
168
+ loadedText: res.text,
169
+ status: Status.LOADED
170
+ }, () => {
171
+ this.props.onLoad(this.props.src, isCached);
172
+ });
173
+ }
174
+ };
175
+
176
+ getClassName() {
177
+ let className = `isvg ${this.state.status}`;
178
+
179
+ if (this.props.className) {
180
+ className += ` ${this.props.className}`;
181
+ }
182
+
183
+ return className;
184
+ }
185
+
186
+ processSVG(svgText) {
187
+ const { uniquifyIDs, uniqueHash } = this.props;
188
+
189
+ if (uniquifyIDs) {
190
+ return uniquifySVGIDs(svgText, uniqueHash || randomString());
191
+ }
192
+
193
+ return svgText;
194
+ }
195
+
196
+ renderContents() {
197
+ switch (this.state.status) {
198
+ case Status.UNSUPPORTED:
199
+ case Status.FAILED:
200
+ return this.props.children;
201
+ default:
202
+ return this.props.preloader;
203
+ }
204
+ }
205
+
206
+ render() {
207
+ let content;
208
+ let html;
209
+
210
+ if (this.state.loadedText) {
211
+ html = {
212
+ __html: this.processSVG(this.state.loadedText)
213
+ };
214
+ }
215
+ else {
216
+ content = this.renderContents();
217
+ }
218
+
219
+ return this.props.wrapper({
220
+ style: this.props.style,
221
+ className: this.getClassName(),
222
+ dangerouslySetInnerHTML: html,
223
+ }, content);
224
+ }
225
+ }
package/src/utils.js ADDED
@@ -0,0 +1,99 @@
1
+ import once from 'once';
2
+
3
+ export const supportsInlineSVG = once(() => {
4
+ /* istanbul ignore next */
5
+ if (!document) {
6
+ return false;
7
+ }
8
+
9
+ const div = document.createElement('div');
10
+ div.innerHTML = '<svg />';
11
+ return div.firstChild && div.firstChild.namespaceURI === 'http://www.w3.org/2000/svg';
12
+ });
13
+
14
+ export const isSupportedEnvironment = once(() =>
15
+ (
16
+ supportsInlineSVG() &&
17
+ typeof window !== 'undefined' && window !== null
18
+ ? window.XMLHttpRequest || window.XDomainRequest
19
+ : false
20
+ )
21
+ );
22
+
23
+ export const randomString = (length = 8) => {
24
+ const letters = 'abcdefghijklmnopqrstuvwxyz';
25
+ const numbers = '1234567890';
26
+ const charset = letters + letters.toUpperCase() + numbers;
27
+
28
+ const randomCharacter = array => array[Math.floor(Math.random() * array.length)];
29
+
30
+ let R = '';
31
+ for (let i = 0; i < length; i++) {
32
+ R += randomCharacter(charset);
33
+ }
34
+ return R;
35
+ };
36
+
37
+ export const uniquifySVGIDs = (() => {
38
+ const mkAttributePattern = attr => `(?:(?:\\s|\\:)${attr})`;
39
+
40
+ const idPattern = new RegExp(`(?:(${(mkAttributePattern('id'))})="([^"]+)")|(?:(${(mkAttributePattern('href'))}|${(mkAttributePattern('role'))}|${(mkAttributePattern('arcrole'))})="\\#([^"]+)")|(?:="url\\(\\#([^\\)]+)\\)")`, 'g');
41
+
42
+ return (svgText, svgID) => {
43
+ const uniquifyID = id => `${id}___${svgID}`;
44
+
45
+ return svgText.replace(idPattern, (m, p1, p2, p3, p4, p5) => { //eslint-disable-line consistent-return
46
+ /* istanbul ignore else */
47
+ if (p2) {
48
+ return `${p1}="${(uniquifyID(p2))}"`;
49
+ }
50
+ else if (p4) {
51
+ return `${p3}="#${(uniquifyID(p4))}"`;
52
+ }
53
+ else if (p5) {
54
+ return `="url(#${(uniquifyID(p5))})"`;
55
+ }
56
+ });
57
+ };
58
+ })();
59
+
60
+ class InlineSVGError extends Error {
61
+ constructor(message) {
62
+ super();
63
+
64
+ this.name = 'InlineSVGError';
65
+ this.isSupportedBrowser = true;
66
+ this.isConfigurationError = false;
67
+ this.isUnsupportedBrowserError = false;
68
+ this.message = message;
69
+
70
+ return this;
71
+ }
72
+ }
73
+
74
+ const createError = (message, attrs) => {
75
+ const err = new InlineSVGError(message);
76
+
77
+ return {
78
+ ...err,
79
+ ...attrs,
80
+ };
81
+ };
82
+
83
+ export const unsupportedBrowserError = message => {
84
+ let newMessage = message;
85
+
86
+ /* istanbul ignore else */
87
+ if (!newMessage) {
88
+ newMessage = 'Unsupported Browser';
89
+ }
90
+
91
+ return createError(newMessage, {
92
+ isSupportedBrowser: false,
93
+ isUnsupportedBrowserError: true
94
+ });
95
+ };
96
+
97
+ export const configurationError = message => createError(message, {
98
+ isConfigurationError: true
99
+ });
package/.codeclimate.yml DELETED
@@ -1,29 +0,0 @@
1
- ---
2
- engines:
3
- eslint:
4
- enabled: true
5
- channel: "eslint-4"
6
- config:
7
- extensions:
8
- - .js
9
- - .jsx
10
- checks:
11
- import/no-duplicates:
12
- enabled: false
13
- no-template-curly-in-string:
14
- enabled: false
15
- import/no-unresolved:
16
- enabled: false
17
- import/no-extraneous-dependencies:
18
- enabled: false
19
- import/no-named-as-default-member:
20
- enabled: false
21
- ratings:
22
- paths:
23
- - "**.js"
24
- - "**.jsx"
25
- exclude_paths:
26
- - lib/**/*
27
- - node_modules/**/*
28
- - standalone/**/*
29
- - tests/**/*
@@ -1,3 +0,0 @@
1
- <component name="CopyrightManager">
2
- <settings default="" />
3
- </component>
@@ -1,7 +0,0 @@
1
- <component name="ProjectDictionaryState">
2
- <dictionary name="gilbarbara">
3
- <words>
4
- <w>uniquify</w>
5
- </words>
6
- </dictionary>
7
- </component>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="Encoding">
4
- <file url="PROJECT" charset="UTF-8" />
5
- </component>
6
- </project>
@@ -1,26 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="ES6ConvertVarToLetConst" enabled="false" level="WARNING" enabled_by_default="false" />
5
- <inspection_tool class="ES6ModulesDependencies" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
6
- <inspection_tool class="ES6UnusedImports" enabled="false" level="WARNING" enabled_by_default="false" />
7
- <inspection_tool class="Eslint" enabled="true" level="ERROR" enabled_by_default="true" />
8
- <inspection_tool class="HtmlUnknownAttribute" enabled="false" level="WARNING" enabled_by_default="false">
9
- <option name="myValues">
10
- <value>
11
- <list size="0" />
12
- </value>
13
- </option>
14
- <option name="myCustomValuesEnabled" value="true" />
15
- </inspection_tool>
16
- <inspection_tool class="JSCheckFunctionSignatures" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
17
- <inspection_tool class="JSMethodCanBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
18
- <inspection_tool class="JSUnresolvedFunction" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
19
- <inspection_tool class="JSUnresolvedVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
20
- <inspection_tool class="JSUnusedGlobalSymbols" enabled="false" level="WARNING" enabled_by_default="false" />
21
- <inspection_tool class="JSValidateTypes" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
22
- <inspection_tool class="NodeModulesDependencies" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
23
- <inspection_tool class="NpmUsedModulesInstalled" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
24
- <inspection_tool class="SassScssResolvedByNameOnly" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
25
- </profile>
26
- </component>
@@ -1,7 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <settings>
3
- <option name="PROJECT_PROFILE" value="Project Default" />
4
- <option name="USE_PROJECT_PROFILE" value="true" />
5
- <version value="1.0" />
6
- </settings>
7
- </component>
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="JavaScriptLibraryMappings">
4
- <file url="file://$PROJECT_DIR$" libraries="{react-inlinesvg/node_modules}" />
5
- <file url="PROJECT" libraries="{classnames-DefinitelyTyped, enzyme-DefinitelyTyped, gulp-DefinitelyTyped, jest-DefinitelyTyped, jsdom-DefinitelyTyped, react-DefinitelyTyped, react-inlinesvg/node_modules, webpack-DefinitelyTyped}" />
6
- <includedPredefinedLibrary name="Node.js Core" />
7
- </component>
8
- </project>
package/.idea/misc.xml DELETED
@@ -1,53 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="JavaScriptSettings">
4
- <option name="languageLevel" value="JSX" />
5
- </component>
6
- <component name="JsBowerSettings">
7
- <exe-path>/usr/local/bin/bower</exe-path>
8
- <config-path />
9
- </component>
10
- <component name="ProjectInspectionProfilesVisibleTreeState">
11
- <entry key="Project Default">
12
- <profile-state>
13
- <expanded-state>
14
- <State>
15
- <id />
16
- </State>
17
- <State>
18
- <id>CSS</id>
19
- </State>
20
- <State>
21
- <id>GeneralJavaScript</id>
22
- </State>
23
- <State>
24
- <id>Invalid elementsCSS</id>
25
- </State>
26
- <State>
27
- <id>JavaScript</id>
28
- </State>
29
- <State>
30
- <id>Less</id>
31
- </State>
32
- <State>
33
- <id>PHP</id>
34
- </State>
35
- <State>
36
- <id>Sass/SCSS</id>
37
- </State>
38
- <State>
39
- <id>TypeScript</id>
40
- </State>
41
- <State>
42
- <id>UnusedPHP</id>
43
- </State>
44
- </expanded-state>
45
- <selected-state>
46
- <State>
47
- <id>SassScssResolvedByNameOnly</id>
48
- </State>
49
- </selected-state>
50
- </profile-state>
51
- </entry>
52
- </component>
53
- </project>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/react-inlinesvg.iml" filepath="$PROJECT_DIR$/.idea/react-inlinesvg.iml" />
6
- </modules>
7
- </component>
8
- </project>
package/.idea/php.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="PhpUnit">
4
- <phpunit_settings>
5
- <PhpUnitSettings load_method="CUSTOM_LOADER" />
6
- </phpunit_settings>
7
- </component>
8
- </project>
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="WEB_MODULE" version="4">
3
- <component name="NewModuleRootManager">
4
- <content url="file://$MODULE_DIR$" />
5
- <orderEntry type="inheritedJdk" />
6
- <orderEntry type="sourceFolder" forTests="false" />
7
- <orderEntry type="library" name="enzyme-DefinitelyTyped" level="application" />
8
- <orderEntry type="library" name="classnames-DefinitelyTyped" level="application" />
9
- <orderEntry type="library" name="gulp-DefinitelyTyped" level="application" />
10
- <orderEntry type="library" name="jest-DefinitelyTyped" level="application" />
11
- <orderEntry type="library" name="jsdom-DefinitelyTyped" level="application" />
12
- <orderEntry type="library" name="react-DefinitelyTyped" level="application" />
13
- <orderEntry type="library" name="webpack-DefinitelyTyped" level="application" />
14
- </component>
15
- </module>
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ScssLintProjectComponent">
4
- <option name="scssLintExecutable" value="$USER_HOME$/.rvm/gems/ruby-2.3.1/bin/scss-lint" />
5
- <option name="pluginEnabled" value="true" />
6
- </component>
7
- </project>
package/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
- </component>
6
- </project>