config-editor-base 1.5.7 → 1.5.8

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/LICENSE.md CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2020 CSS-Electronics
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2020 CSS-Electronics
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -1,165 +1,165 @@
1
- # Config Editor - Base Module
2
-
3
- This project includes a React based JSON Schema editor.
4
-
5
- [![NPM](https://img.shields.io/npm/v/config-editor-base.svg)](https://www.npmjs.com/package/config-editor-base) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
6
-
7
- ### Installation
8
-
9
- ```bash
10
- npm install --save config-editor-base
11
- ```
12
-
13
- ---
14
-
15
- ### Development testing
16
-
17
- You can directly test the "raw" configuration editor by cloning this repository and running below `npm install` in root and in the `example/` folder. After this, run `npm start` in the root as well as in the `example/` folder.
18
-
19
- ---
20
-
21
- ### Publishing a new package via npm
22
-
23
- To publish your own custom version as an npm package, you can modify the `package.json` and run `npm publish`. You'll need to be logged in first.
24
-
25
- ---
26
-
27
- ### Usage in a parent app
28
-
29
- The module uses redux, hence you'll need to import the base module and the `reducer` as follows:
30
-
31
- ```jsx
32
- // reducers.js
33
-
34
- import { combineReducers } from 'redux'
35
- import alert from './alert/reducer'
36
-
37
- import { editor } from 'config-editor-base'
38
-
39
- const rootReducer = combineReducers({
40
- alert,
41
- editor
42
- })
43
-
44
- export default rootReducer
45
- ```
46
-
47
- In the parent App we can load an Editor module, which can be constructed as below:
48
-
49
- ```jsx
50
- import React from 'react'
51
- import { connect } from 'react-redux'
52
-
53
- import { EncryptionModal } from 'config-editor-tools'
54
- import { EditorSection } from 'config-editor-base'
55
-
56
- import * as actionsAlert from '../alert/actions'
57
- import AlertContainer from '../alert/AlertContainer'
58
-
59
- class Editor extends React.Component {
60
- render() {
61
- let editorTools = [
62
- {
63
- name: 'encryption-modal',
64
- comment: 'Encryption tool',
65
- class: 'fa fa-lock',
66
- modal: <EncryptionModal showAlert={this.props.showAlert} />
67
- }
68
- ]
69
-
70
- return (
71
- <div className='file-explorer'>
72
- <div className='fe-body fe-body-offline'>
73
- <AlertContainer />
74
- <EditorSection
75
- editorTools={editorTools}
76
- showAlert={this.props.showAlert}
77
- />
78
- </div>
79
- </div>
80
- )
81
- }
82
- }
83
-
84
- const mapDispatchToProps = (dispatch) => {
85
- return {
86
- showAlert: (type, message) =>
87
- dispatch(actionsAlert.set({ type: type, message: message }))
88
- }
89
- }
90
-
91
- export default connect(null, mapDispatchToProps)(Editor)
92
- ```
93
-
94
- ---
95
-
96
- ## Parsing embedded Rule Schema and UISchema files
97
-
98
- The [config editor](https://github.com/CSS-Electronics/config-editor) can take a list of UIschema and Rule Schema files. This enables the editor to "auto-load" the UIschemas upon initial load, as well as "auto-load" the Rule Schema files matching the revision of the loaded Configuration File.
99
-
100
- Note that the parsed list of files should match the actual files that are included in the config-editor-base `dist/` folder.
101
-
102
- For example, the Rule Schema for `"schema-01.02.json | CANedge2"` should be contained in `dist/schema/CANedge2/schema-01.02.json`.
103
-
104
- The syntax for parsing these lists is as below (in the [config-editor](https://github.com/CSS-Electronics/config-editor) repo `Editor.js` file):
105
-
106
- ```jsx
107
-
108
- // define UIschema and Rule Schema names for auto-loading embedded schema files
109
- export const uiSchemaAry = [
110
- "uischema-01.02.json | Simple",
111
- "uischema-01.02.json | Advanced",
112
- ];
113
-
114
- export const schemaAry = [
115
- "schema-01.02.json | CANedge2",
116
- "schema-01.02.json | CANedge1",
117
- "schema-00.07.json | CANedge2",
118
- "schema-00.07.json | CANedge1",
119
- ];
120
-
121
- ...
122
-
123
- <EditorSection
124
- editorTools={editorTools}
125
- showAlert={this.props.showAlert}
126
- uiSchemaAry={uiSchemaAry}
127
- schemaAry={schemaAry}
128
- />
129
- ...
130
-
131
- ```
132
-
133
- Note that the code distinguishes between a `config-XX.YY.json` file loaded from a CANedge1 and CANedge2 unit. This is done by evaluating whether a `connect` section exists or not in the Configuration File. Based on this test, the editor either loads the Rule Schema for the CANedge2 (if `connect` exists) or the CANedge1.
134
-
135
-
136
- ---
137
-
138
- ## Parsing S3 functionality
139
-
140
- The config editor also supports various S3 calls, e.g. for loading Rule Schema and Configuration Files from a device S3 folder - as well as submitting updated Configuration Files to S3. See the [CANcloud](https://github.com/CSS-Electronics/cancloud) repository for an example of this implementation.
141
-
142
- ---
143
-
144
- ## Regarding styling
145
-
146
- The config editor relies on styling from the parent application. For examples of styling, see the CANedge configuration editor.
147
-
148
- ---
149
- ## Regarding JSON Schema files
150
-
151
- The module expects to find JSON Schema files in the structure below to facilitate auto-loading of these:
152
-
153
- ```
154
- /
155
- |-- dist/
156
- |-- schema/
157
- |-- Advanced/
158
- |-- uischema-XX.YY.json
159
- |-- Simple/
160
- |-- uischema-XX.YY.json
161
- |-- CANedge1/
162
- |-- schema-XX.YY.json
163
- |-- CANedge2/
164
- |-- schema-XX.YY.json
165
- ```
1
+ # Config Editor - Base Module
2
+
3
+ This project includes a React based JSON Schema editor.
4
+
5
+ [![NPM](https://img.shields.io/npm/v/config-editor-base.svg)](https://www.npmjs.com/package/config-editor-base) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ npm install --save config-editor-base
11
+ ```
12
+
13
+ ---
14
+
15
+ ### Development testing
16
+
17
+ You can directly test the "raw" configuration editor by cloning this repository and running below `npm install` in root and in the `example/` folder. After this, run `npm start` in the root as well as in the `example/` folder.
18
+
19
+ ---
20
+
21
+ ### Publishing a new package via npm
22
+
23
+ To publish your own custom version as an npm package, you can modify the `package.json` and run `npm publish`. You'll need to be logged in first.
24
+
25
+ ---
26
+
27
+ ### Usage in a parent app
28
+
29
+ The module uses redux, hence you'll need to import the base module and the `reducer` as follows:
30
+
31
+ ```jsx
32
+ // reducers.js
33
+
34
+ import { combineReducers } from 'redux'
35
+ import alert from './alert/reducer'
36
+
37
+ import { editor } from 'config-editor-base'
38
+
39
+ const rootReducer = combineReducers({
40
+ alert,
41
+ editor
42
+ })
43
+
44
+ export default rootReducer
45
+ ```
46
+
47
+ In the parent App we can load an Editor module, which can be constructed as below:
48
+
49
+ ```jsx
50
+ import React from 'react'
51
+ import { connect } from 'react-redux'
52
+
53
+ import { EncryptionModal } from 'config-editor-tools'
54
+ import { EditorSection } from 'config-editor-base'
55
+
56
+ import * as actionsAlert from '../alert/actions'
57
+ import AlertContainer from '../alert/AlertContainer'
58
+
59
+ class Editor extends React.Component {
60
+ render() {
61
+ let editorTools = [
62
+ {
63
+ name: 'encryption-modal',
64
+ comment: 'Encryption tool',
65
+ class: 'fa fa-lock',
66
+ modal: <EncryptionModal showAlert={this.props.showAlert} />
67
+ }
68
+ ]
69
+
70
+ return (
71
+ <div className='file-explorer'>
72
+ <div className='fe-body fe-body-offline'>
73
+ <AlertContainer />
74
+ <EditorSection
75
+ editorTools={editorTools}
76
+ showAlert={this.props.showAlert}
77
+ />
78
+ </div>
79
+ </div>
80
+ )
81
+ }
82
+ }
83
+
84
+ const mapDispatchToProps = (dispatch) => {
85
+ return {
86
+ showAlert: (type, message) =>
87
+ dispatch(actionsAlert.set({ type: type, message: message }))
88
+ }
89
+ }
90
+
91
+ export default connect(null, mapDispatchToProps)(Editor)
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Parsing embedded Rule Schema and UISchema files
97
+
98
+ The [config editor](https://github.com/CSS-Electronics/config-editor) can take a list of UIschema and Rule Schema files. This enables the editor to "auto-load" the UIschemas upon initial load, as well as "auto-load" the Rule Schema files matching the revision of the loaded Configuration File.
99
+
100
+ Note that the parsed list of files should match the actual files that are included in the config-editor-base `dist/` folder.
101
+
102
+ For example, the Rule Schema for `"schema-01.02.json | CANedge2"` should be contained in `dist/schema/CANedge2/schema-01.02.json`.
103
+
104
+ The syntax for parsing these lists is as below (in the [config-editor](https://github.com/CSS-Electronics/config-editor) repo `Editor.js` file):
105
+
106
+ ```jsx
107
+
108
+ // define UIschema and Rule Schema names for auto-loading embedded schema files
109
+ export const uiSchemaAry = [
110
+ "uischema-01.02.json | Simple",
111
+ "uischema-01.02.json | Advanced",
112
+ ];
113
+
114
+ export const schemaAry = [
115
+ "schema-01.02.json | CANedge2",
116
+ "schema-01.02.json | CANedge1",
117
+ "schema-00.07.json | CANedge2",
118
+ "schema-00.07.json | CANedge1",
119
+ ];
120
+
121
+ ...
122
+
123
+ <EditorSection
124
+ editorTools={editorTools}
125
+ showAlert={this.props.showAlert}
126
+ uiSchemaAry={uiSchemaAry}
127
+ schemaAry={schemaAry}
128
+ />
129
+ ...
130
+
131
+ ```
132
+
133
+ Note that the code distinguishes between a `config-XX.YY.json` file loaded from a CANedge1 and CANedge2 unit. This is done by evaluating whether a `connect` section exists or not in the Configuration File. Based on this test, the editor either loads the Rule Schema for the CANedge2 (if `connect` exists) or the CANedge1.
134
+
135
+
136
+ ---
137
+
138
+ ## Parsing S3 functionality
139
+
140
+ The config editor also supports various S3 calls, e.g. for loading Rule Schema and Configuration Files from a device S3 folder - as well as submitting updated Configuration Files to S3. See the [CANcloud](https://github.com/CSS-Electronics/cancloud) repository for an example of this implementation.
141
+
142
+ ---
143
+
144
+ ## Regarding styling
145
+
146
+ The config editor relies on styling from the parent application. For examples of styling, see the CANedge configuration editor.
147
+
148
+ ---
149
+ ## Regarding JSON Schema files
150
+
151
+ The module expects to find JSON Schema files in the structure below to facilitate auto-loading of these:
152
+
153
+ ```
154
+ /
155
+ |-- dist/
156
+ |-- schema/
157
+ |-- Advanced/
158
+ |-- uischema-XX.YY.json
159
+ |-- Simple/
160
+ |-- uischema-XX.YY.json
161
+ |-- CANedge1/
162
+ |-- schema-XX.YY.json
163
+ |-- CANedge2/
164
+ |-- schema-XX.YY.json
165
+ ```
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ var utils = require('react-jsonschema-form-pagination/lib/utils');
12
12
  var reactGhLikeDiff = require('react-gh-like-diff');
13
13
 
14
14
  function _extends() {
15
- _extends = Object.assign || function (target) {
15
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
16
16
  for (var i = 1; i < arguments.length; i++) {
17
17
  var source = arguments[i];
18
18
 
@@ -25,14 +25,22 @@ function _extends() {
25
25
 
26
26
  return target;
27
27
  };
28
-
29
28
  return _extends.apply(this, arguments);
30
29
  }
31
30
 
32
31
  function _inheritsLoose(subClass, superClass) {
33
32
  subClass.prototype = Object.create(superClass.prototype);
34
33
  subClass.prototype.constructor = subClass;
35
- subClass.__proto__ = superClass;
34
+
35
+ _setPrototypeOf(subClass, superClass);
36
+ }
37
+
38
+ function _setPrototypeOf(o, p) {
39
+ _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
40
+ o.__proto__ = p;
41
+ return o;
42
+ };
43
+ return _setPrototypeOf(o, p);
36
44
  }
37
45
 
38
46
  function _assertThisInitialized(self) {
@@ -43,6 +51,41 @@ function _assertThisInitialized(self) {
43
51
  return self;
44
52
  }
45
53
 
54
+ var SET = "alert/SET";
55
+ var CLEAR = "alert/CLEAR";
56
+ var alertId = 0;
57
+ var set = function set(alert) {
58
+ var id = alertId++;
59
+ return function (dispatch) {
60
+ if (alert.type == "warning") {
61
+ setTimeout(function () {
62
+ dispatch({
63
+ type: CLEAR,
64
+ alert: {
65
+ id: id
66
+ }
67
+ });
68
+ }, 10000);
69
+ } else if (alert.type !== "danger" || alert.autoClear) {
70
+ setTimeout(function () {
71
+ dispatch({
72
+ type: CLEAR,
73
+ alert: {
74
+ id: id
75
+ }
76
+ });
77
+ }, 5000);
78
+ }
79
+
80
+ dispatch({
81
+ type: SET,
82
+ alert: Object.assign({}, alert, {
83
+ id: id
84
+ })
85
+ });
86
+ };
87
+ };
88
+
46
89
  var demoConfig = 'config-01.04.json';
47
90
  var regexUISchemaPublic = new RegExp(/^uischema-\d{2}\.\d{2}\.json/, 'g');
48
91
  var regexSchemaPublic = new RegExp(/^schema-\d{2}\.\d{2}\.json/, 'g');
@@ -241,6 +284,16 @@ var handleUploadedFile = function handleUploadedFile(file, dropdown, schemaAry,
241
284
  dispatch(publicSchemaFiles(file.name, schemaAry, contentJSON, uiSchemaAry));
242
285
  }
243
286
 
287
+ var configIncludesServerDetails = JSON.stringify(contentJSON, null, 2).includes("http://") || JSON.stringify(contentJSON, null, 2).includes("https://");
288
+
289
+ if (configIncludesServerDetails) {
290
+ dispatch(set({
291
+ type: "warning",
292
+ message: "If your device is already connected to your server, changes made via the SD will be overwritten by the server Configuration File",
293
+ autoClear: false
294
+ }));
295
+ }
296
+
244
297
  dispatch(setConfigContentLocal(content));
245
298
  dispatch(setConfigContent(contentJSON));
246
299
  dispatch(resetLocalConfigList());
@@ -1555,14 +1608,15 @@ var lodash = createCommonjsModule(function (module, exports) {
1555
1608
  var undefined$1;
1556
1609
 
1557
1610
  /** Used as the semantic version number. */
1558
- var VERSION = '4.17.20';
1611
+ var VERSION = '4.17.21';
1559
1612
 
1560
1613
  /** Used as the size to enable large array optimizations. */
1561
1614
  var LARGE_ARRAY_SIZE = 200;
1562
1615
 
1563
1616
  /** Error message constants. */
1564
1617
  var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
1565
- FUNC_ERROR_TEXT = 'Expected a function';
1618
+ FUNC_ERROR_TEXT = 'Expected a function',
1619
+ INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
1566
1620
 
1567
1621
  /** Used to stand-in for `undefined` hash values. */
1568
1622
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
@@ -1695,10 +1749,11 @@ var lodash = createCommonjsModule(function (module, exports) {
1695
1749
  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
1696
1750
  reHasRegExpChar = RegExp(reRegExpChar.source);
1697
1751
 
1698
- /** Used to match leading and trailing whitespace. */
1699
- var reTrim = /^\s+|\s+$/g,
1700
- reTrimStart = /^\s+/,
1701
- reTrimEnd = /\s+$/;
1752
+ /** Used to match leading whitespace. */
1753
+ var reTrimStart = /^\s+/;
1754
+
1755
+ /** Used to match a single whitespace character. */
1756
+ var reWhitespace = /\s/;
1702
1757
 
1703
1758
  /** Used to match wrap detail comments. */
1704
1759
  var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
@@ -1708,6 +1763,18 @@ var lodash = createCommonjsModule(function (module, exports) {
1708
1763
  /** Used to match words composed of alphanumeric characters. */
1709
1764
  var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
1710
1765
 
1766
+ /**
1767
+ * Used to validate the `validate` option in `_.template` variable.
1768
+ *
1769
+ * Forbids characters which could potentially change the meaning of the function argument definition:
1770
+ * - "()," (modification of function parameters)
1771
+ * - "=" (default value)
1772
+ * - "[]{}" (destructuring of function parameters)
1773
+ * - "/" (beginning of a comment)
1774
+ * - whitespace
1775
+ */
1776
+ var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
1777
+
1711
1778
  /** Used to match backslashes in property paths. */
1712
1779
  var reEscapeChar = /\\(\\)?/g;
1713
1780
 
@@ -2536,6 +2603,19 @@ var lodash = createCommonjsModule(function (module, exports) {
2536
2603
  });
2537
2604
  }
2538
2605
 
2606
+ /**
2607
+ * The base implementation of `_.trim`.
2608
+ *
2609
+ * @private
2610
+ * @param {string} string The string to trim.
2611
+ * @returns {string} Returns the trimmed string.
2612
+ */
2613
+ function baseTrim(string) {
2614
+ return string
2615
+ ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
2616
+ : string;
2617
+ }
2618
+
2539
2619
  /**
2540
2620
  * The base implementation of `_.unary` without support for storing metadata.
2541
2621
  *
@@ -2869,6 +2949,21 @@ var lodash = createCommonjsModule(function (module, exports) {
2869
2949
  : asciiToArray(string);
2870
2950
  }
2871
2951
 
2952
+ /**
2953
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
2954
+ * character of `string`.
2955
+ *
2956
+ * @private
2957
+ * @param {string} string The string to inspect.
2958
+ * @returns {number} Returns the index of the last non-whitespace character.
2959
+ */
2960
+ function trimmedEndIndex(string) {
2961
+ var index = string.length;
2962
+
2963
+ while (index-- && reWhitespace.test(string.charAt(index))) {}
2964
+ return index;
2965
+ }
2966
+
2872
2967
  /**
2873
2968
  * Used by `_.unescape` to convert HTML entities to characters.
2874
2969
  *
@@ -14037,7 +14132,7 @@ var lodash = createCommonjsModule(function (module, exports) {
14037
14132
  if (typeof value != 'string') {
14038
14133
  return value === 0 ? value : +value;
14039
14134
  }
14040
- value = value.replace(reTrim, '');
14135
+ value = baseTrim(value);
14041
14136
  var isBinary = reIsBinary.test(value);
14042
14137
  return (isBinary || reIsOctal.test(value))
14043
14138
  ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
@@ -16409,6 +16504,12 @@ var lodash = createCommonjsModule(function (module, exports) {
16409
16504
  if (!variable) {
16410
16505
  source = 'with (obj) {\n' + source + '\n}\n';
16411
16506
  }
16507
+ // Throw an error if a forbidden character was found in `variable`, to prevent
16508
+ // potential command injection attacks.
16509
+ else if (reForbiddenIdentifierChars.test(variable)) {
16510
+ throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
16511
+ }
16512
+
16412
16513
  // Cleanup code by stripping empty strings.
16413
16514
  source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
16414
16515
  .replace(reEmptyStringMiddle, '$1')
@@ -16522,7 +16623,7 @@ var lodash = createCommonjsModule(function (module, exports) {
16522
16623
  function trim(string, chars, guard) {
16523
16624
  string = toString(string);
16524
16625
  if (string && (guard || chars === undefined$1)) {
16525
- return string.replace(reTrim, '');
16626
+ return baseTrim(string);
16526
16627
  }
16527
16628
  if (!string || !(chars = baseToString(chars))) {
16528
16629
  return string;
@@ -16557,7 +16658,7 @@ var lodash = createCommonjsModule(function (module, exports) {
16557
16658
  function trimEnd(string, chars, guard) {
16558
16659
  string = toString(string);
16559
16660
  if (string && (guard || chars === undefined$1)) {
16560
- return string.replace(reTrimEnd, '');
16661
+ return string.slice(0, trimmedEndIndex(string) + 1);
16561
16662
  }
16562
16663
  if (!string || !(chars = baseToString(chars))) {
16563
16664
  return string;