@todoist/react-interpolate 0.0.0-stage → 2.2.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/LICENSE +21 -0
- package/README.md +221 -2
- package/dist/react-interpolate.cjs +444 -0
- package/dist/react-interpolate.d.ts +18 -0
- package/dist/react-interpolate.min.cjs +1 -0
- package/dist/react-interpolate.min.mjs +1 -0
- package/dist/react-interpolate.mjs +426 -0
- package/package.json +81 -5
- package/src/constants.js +11 -0
- package/src/index.js +5 -0
- package/src/interpolate.js +93 -0
- package/src/lexer.js +62 -0
- package/src/node.js +65 -0
- package/src/parser.js +166 -0
- package/src/react-interpolate.d.ts +18 -0
- package/src/syntax.js +33 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var React=require("react"),PropTypes=require("prop-types"),_classCallCheck=require("@babel/runtime/helpers/classCallCheck"),_createClass=require("@babel/runtime/helpers/createClass"),_objectWithoutProperties=require("@babel/runtime/helpers/objectWithoutProperties");function _interopDefaultLegacy(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var React__default=_interopDefaultLegacy(React),PropTypes__default=_interopDefaultLegacy(PropTypes),_classCallCheck__default=_interopDefaultLegacy(_classCallCheck),_createClass__default=_interopDefaultLegacy(_createClass),_objectWithoutProperties__default=_interopDefaultLegacy(_objectWithoutProperties),TOKEN_PLACEHOLDER="TOKEN_PLACEHOLDER",TOKEN_OPEN_TAG="TOKEN_OPEN_TAG",TOKEN_CLOSE_TAG="TOKEN_CLOSE_TAG",TOKEN_SELF_TAG="TOKEN_SELF_TAG",TOKEN_TEXT="TOKEN_TEXT",NODE_FRAGMENT="NODE_FRAGMENT",NODE_TAG_ELEMENT="NODE_TAG_ELEMENT",NODE_VOID_ELEMENT="NODE_VOID_ELEMENT",NODE_PLACEHOLDER="NODE_PLACEHOLDER",NODE_TEXT="NODE_TEXT",_excluded=["type","children"],Node=function(){function e(t){var r=t.type,n=t.children,a=_objectWithoutProperties__default.default(t,_excluded);for(var o in _classCallCheck__default.default(this,e),this.type=r,this.children=n||[],a)this[o]=a[o];a.token&&(this.string=a.token.string)}return _createClass__default.default(e,[{key:"appendChild",value:function(e){this.children.push(e)}},{key:"isLeaf",get:function(){return 0===this.children.length}}]),e}();Node.createTagNode=function(e,t){return new Node({type:NODE_TAG_ELEMENT,children:t,name:e.name,token:e})},Node.createFragmentNode=function(e){return new Node({type:NODE_FRAGMENT,children:e})},Node.createVoidNode=function(e){return new Node({type:NODE_VOID_ELEMENT,name:e.name,token:e})},Node.createTextNode=function(e){return new Node({type:NODE_TEXT,text:e.string,token:e})},Node.createPlaceholderNode=function(e){return new Node({type:NODE_PLACEHOLDER,name:e.name,token:e})};var SYNTAX_BUILT_IN=[{type:TOKEN_PLACEHOLDER,regex:/{\s*(\w+)\s*}/g},{type:TOKEN_OPEN_TAG,regex:/<(\w+)>/g},{type:TOKEN_CLOSE_TAG,regex:/<\/(\w+)>/g},{type:TOKEN_SELF_TAG,regex:/<(\w+)\s*\/>/g}],SYNTAX_I18NEXT=[{type:TOKEN_PLACEHOLDER,regex:/{{\s*(\w+)\s*}}/g},{type:TOKEN_OPEN_TAG,regex:/<(\w+)>/g},{type:TOKEN_CLOSE_TAG,regex:/<\/(\w+)>/g},{type:TOKEN_SELF_TAG,regex:/<(\w+)\s*\/>/g}];function _createForOfIteratorHelper(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,u=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return i=e.done,e},e:function(e){u=!0,o=e},f:function(){try{i||null==r.return||r.return()}finally{if(u)throw o}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function lexer(e,t){var r,n=[],a=_createForOfIteratorHelper(t);try{for(a.s();!(r=a.n()).done;)for(var o,i=r.value,u=i.type,l=i.regex;null!==(o=l.exec(e));)n.push({type:u,string:o[0],name:o[1],start:o.index,end:o.index+o[0].length})}catch(e){a.e(e)}finally{a.f()}n.sort(function(e,t){return e.start-t.start});var c=[],s=0;n.forEach(function(t){if(t.start!==s){var r=t.start,n=e.substring(s,r);c.push({type:TOKEN_TEXT,string:n,text:n,start:s,end:r}),s=t.end}else s=t.end});var _=e.substring(s);return""!==_&&c.push({type:TOKEN_TEXT,string:_,start:s,end:e.length}),[].concat(c,n).sort(function(e,t){return e.start-t.start})}function parser(e,t){t||(t=SYNTAX_BUILT_IN);var r=lexer(e,t);return new Parser(r).parse()}var SYNTAX_ERROR="Syntax error. Please check if each open tag is closed correctly",EPSILON={type:"EPSILON"},Parser=function(){function e(t){_classCallCheck__default.default(this,e),this.tokens=[].concat(t),this.tags=[]}return _createClass__default.default(e,[{key:"parse",value:function(){var e=this.document();if(!this.predict(EPSILON.type))throw new Error(SYNTAX_ERROR);return e}},{key:"document",value:function(){var e=this.elementOrData();return Node.createFragmentNode(e)}},{key:"element",value:function(){var e=this.openTag(),t=this.elementOrData();return this.endTag(),Node.createTagNode(e,t)}},{key:"openTag",value:function(){if(!this.predict(TOKEN_OPEN_TAG))throw new Error(SYNTAX_ERROR);return this.pushTag(this.lookahead),this.match(TOKEN_OPEN_TAG)}},{key:"elementOrData",value:function(){var e=[];if(this.predict(TOKEN_OPEN_TAG)&&(e.push(this.element()),e=e.concat(this.elementOrData())),this.predict(TOKEN_SELF_TAG,TOKEN_TEXT,TOKEN_PLACEHOLDER)){var t,r=this.match(this.lookahead.type);switch(r.type){case TOKEN_SELF_TAG:t=Node.createVoidNode(r);break;case TOKEN_TEXT:t=Node.createTextNode(r);break;case TOKEN_PLACEHOLDER:t=Node.createPlaceholderNode(r)}e.push(t),e=e.concat(this.elementOrData())}return e}},{key:"endTag",value:function(){if(!this.predict(TOKEN_CLOSE_TAG))throw new Error(SYNTAX_ERROR);if(this.tags.pop().name!==this.lookahead.name)throw new Error(SYNTAX_ERROR);this.match(TOKEN_CLOSE_TAG)}},{key:"lookahead",get:function(){return 0===this.tokens.length?EPSILON:this.tokens[0]}},{key:"predict",value:function(){for(var e=arguments.length,t=new Array(e),r=0;r<e;r++)t[r]=arguments[r];return t.includes(this.lookahead.type)}},{key:"match",value:function(e){if(!this.predict(e))throw new Error(SYNTAX_ERROR);return this.tokens.shift()}},{key:"pushTag",value:function(e){this.tags.push(e)}}]),e}(),createElement=function e(t,r,n){var a=t.children.map(function(t,a){return React__default.default.createElement(React__default.default.Fragment,{key:n+a},e(t,r,n))});switch(t.type){case NODE_TEXT:return t.text;case NODE_FRAGMENT:return React__default.default.createElement(React__default.default.Fragment,null,a);case NODE_VOID_ELEMENT:var o=r[t.name];return"function"==typeof o?o():o||React__default.default.createElement(t.name,null);case NODE_TAG_ELEMENT:var i=r[t.name];if(void 0===i)return React__default.default.createElement(t.name,null,a);if("function"==typeof i)return i(a);if(React__default.default.isValidElement(i)){if(0!==React__default.default.Children.count(i.props.children))throw new Error("when passing an element as value, the element should not contains children");return React__default.default.cloneElement(i,{children:a})}throw new Error('Invalid mapping value for "'.concat(t.name,'". Only element or render function are accepted'));case NODE_PLACEHOLDER:var u=r[t.name];return void 0===u?(console.warn('missing "'.concat(t.name,'" in mapping')),t.string):"function"==typeof u?u():u;default:return}};function Interpolate(e){var t=e.string,r=e.syntax,n=e.mapping,a=void 0===n?{}:n,o=e.graceful,i=void 0===o||o;try{var u=parser(t,r);return createElement(u,a,t)}catch(e){if(i)return console.error(e),t;throw e}}Interpolate.propTypes={string:PropTypes__default.default.string.isRequired,mapping:PropTypes__default.default.object,graceful:PropTypes__default.default.bool},exports.SYNTAX_BUILT_IN=SYNTAX_BUILT_IN,exports.SYNTAX_I18NEXT=SYNTAX_I18NEXT,exports.TOKEN_CLOSE_TAG=TOKEN_CLOSE_TAG,exports.TOKEN_OPEN_TAG=TOKEN_OPEN_TAG,exports.TOKEN_PLACEHOLDER=TOKEN_PLACEHOLDER,exports.TOKEN_SELF_TAG=TOKEN_SELF_TAG,exports.default=Interpolate;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from"react";import PropTypes from"prop-types";import _classCallCheck from"@babel/runtime/helpers/classCallCheck";import _createClass from"@babel/runtime/helpers/createClass";import _objectWithoutProperties from"@babel/runtime/helpers/objectWithoutProperties";var TOKEN_PLACEHOLDER="TOKEN_PLACEHOLDER",TOKEN_OPEN_TAG="TOKEN_OPEN_TAG",TOKEN_CLOSE_TAG="TOKEN_CLOSE_TAG",TOKEN_SELF_TAG="TOKEN_SELF_TAG",TOKEN_TEXT="TOKEN_TEXT",NODE_FRAGMENT="NODE_FRAGMENT",NODE_TAG_ELEMENT="NODE_TAG_ELEMENT",NODE_VOID_ELEMENT="NODE_VOID_ELEMENT",NODE_PLACEHOLDER="NODE_PLACEHOLDER",NODE_TEXT="NODE_TEXT",_excluded=["type","children"],Node=function(){function e(t){var r=t.type,n=t.children,a=_objectWithoutProperties(t,_excluded);for(var o in _classCallCheck(this,e),this.type=r,this.children=n||[],a)this[o]=a[o];a.token&&(this.string=a.token.string)}return _createClass(e,[{key:"appendChild",value:function(e){this.children.push(e)}},{key:"isLeaf",get:function(){return 0===this.children.length}}]),e}();Node.createTagNode=function(e,t){return new Node({type:NODE_TAG_ELEMENT,children:t,name:e.name,token:e})},Node.createFragmentNode=function(e){return new Node({type:NODE_FRAGMENT,children:e})},Node.createVoidNode=function(e){return new Node({type:NODE_VOID_ELEMENT,name:e.name,token:e})},Node.createTextNode=function(e){return new Node({type:NODE_TEXT,text:e.string,token:e})},Node.createPlaceholderNode=function(e){return new Node({type:NODE_PLACEHOLDER,name:e.name,token:e})};var SYNTAX_BUILT_IN=[{type:TOKEN_PLACEHOLDER,regex:/{\s*(\w+)\s*}/g},{type:TOKEN_OPEN_TAG,regex:/<(\w+)>/g},{type:TOKEN_CLOSE_TAG,regex:/<\/(\w+)>/g},{type:TOKEN_SELF_TAG,regex:/<(\w+)\s*\/>/g}],SYNTAX_I18NEXT=[{type:TOKEN_PLACEHOLDER,regex:/{{\s*(\w+)\s*}}/g},{type:TOKEN_OPEN_TAG,regex:/<(\w+)>/g},{type:TOKEN_CLOSE_TAG,regex:/<\/(\w+)>/g},{type:TOKEN_SELF_TAG,regex:/<(\w+)\s*\/>/g}];function _createForOfIteratorHelper(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,c=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return i=e.done,e},e:function(e){c=!0,o=e},f:function(){try{i||null==r.return||r.return()}finally{if(c)throw o}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function lexer(e,t){var r,n=[],a=_createForOfIteratorHelper(t);try{for(a.s();!(r=a.n()).done;)for(var o,i=r.value,c=i.type,E=i.regex;null!==(o=E.exec(e));)n.push({type:c,string:o[0],name:o[1],start:o.index,end:o.index+o[0].length})}catch(e){a.e(e)}finally{a.f()}n.sort(function(e,t){return e.start-t.start});var s=[],u=0;n.forEach(function(t){if(t.start!==u){var r=t.start,n=e.substring(u,r);s.push({type:TOKEN_TEXT,string:n,text:n,start:u,end:r}),u=t.end}else u=t.end});var l=e.substring(u);return""!==l&&s.push({type:TOKEN_TEXT,string:l,start:u,end:e.length}),[].concat(s,n).sort(function(e,t){return e.start-t.start})}function parser(e,t){t||(t=SYNTAX_BUILT_IN);var r=lexer(e,t);return new Parser(r).parse()}var SYNTAX_ERROR="Syntax error. Please check if each open tag is closed correctly",EPSILON={type:"EPSILON"},Parser=function(){function e(t){_classCallCheck(this,e),this.tokens=[].concat(t),this.tags=[]}return _createClass(e,[{key:"parse",value:function(){var e=this.document();if(!this.predict(EPSILON.type))throw new Error(SYNTAX_ERROR);return e}},{key:"document",value:function(){var e=this.elementOrData();return Node.createFragmentNode(e)}},{key:"element",value:function(){var e=this.openTag(),t=this.elementOrData();return this.endTag(),Node.createTagNode(e,t)}},{key:"openTag",value:function(){if(!this.predict(TOKEN_OPEN_TAG))throw new Error(SYNTAX_ERROR);return this.pushTag(this.lookahead),this.match(TOKEN_OPEN_TAG)}},{key:"elementOrData",value:function(){var e=[];if(this.predict(TOKEN_OPEN_TAG)&&(e.push(this.element()),e=e.concat(this.elementOrData())),this.predict(TOKEN_SELF_TAG,TOKEN_TEXT,TOKEN_PLACEHOLDER)){var t,r=this.match(this.lookahead.type);switch(r.type){case TOKEN_SELF_TAG:t=Node.createVoidNode(r);break;case TOKEN_TEXT:t=Node.createTextNode(r);break;case TOKEN_PLACEHOLDER:t=Node.createPlaceholderNode(r)}e.push(t),e=e.concat(this.elementOrData())}return e}},{key:"endTag",value:function(){if(!this.predict(TOKEN_CLOSE_TAG))throw new Error(SYNTAX_ERROR);if(this.tags.pop().name!==this.lookahead.name)throw new Error(SYNTAX_ERROR);this.match(TOKEN_CLOSE_TAG)}},{key:"lookahead",get:function(){return 0===this.tokens.length?EPSILON:this.tokens[0]}},{key:"predict",value:function(){for(var e=arguments.length,t=new Array(e),r=0;r<e;r++)t[r]=arguments[r];return t.includes(this.lookahead.type)}},{key:"match",value:function(e){if(!this.predict(e))throw new Error(SYNTAX_ERROR);return this.tokens.shift()}},{key:"pushTag",value:function(e){this.tags.push(e)}}]),e}(),createElement=function e(t,r,n){var a=t.children.map(function(t,a){return React.createElement(React.Fragment,{key:n+a},e(t,r,n))});switch(t.type){case NODE_TEXT:return t.text;case NODE_FRAGMENT:return React.createElement(React.Fragment,null,a);case NODE_VOID_ELEMENT:var o=r[t.name];return"function"==typeof o?o():o||React.createElement(t.name,null);case NODE_TAG_ELEMENT:var i=r[t.name];if(void 0===i)return React.createElement(t.name,null,a);if("function"==typeof i)return i(a);if(React.isValidElement(i)){if(0!==React.Children.count(i.props.children))throw new Error("when passing an element as value, the element should not contains children");return React.cloneElement(i,{children:a})}throw new Error('Invalid mapping value for "'.concat(t.name,'". Only element or render function are accepted'));case NODE_PLACEHOLDER:var c=r[t.name];return void 0===c?(console.warn('missing "'.concat(t.name,'" in mapping')),t.string):"function"==typeof c?c():c;default:return}};function Interpolate(e){var t=e.string,r=e.syntax,n=e.mapping,a=void 0===n?{}:n,o=e.graceful,i=void 0===o||o;try{var c=parser(t,r);return createElement(c,a,t)}catch(e){if(i)return console.error(e),t;throw e}}Interpolate.propTypes={string:PropTypes.string.isRequired,mapping:PropTypes.object,graceful:PropTypes.bool};export{SYNTAX_BUILT_IN,SYNTAX_I18NEXT,TOKEN_CLOSE_TAG,TOKEN_OPEN_TAG,TOKEN_PLACEHOLDER,TOKEN_SELF_TAG,Interpolate as default};
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
|
|
4
|
+
import _createClass from '@babel/runtime/helpers/createClass';
|
|
5
|
+
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
|
|
6
|
+
|
|
7
|
+
var TOKEN_PLACEHOLDER = 'TOKEN_PLACEHOLDER';
|
|
8
|
+
var TOKEN_OPEN_TAG = 'TOKEN_OPEN_TAG';
|
|
9
|
+
var TOKEN_CLOSE_TAG = 'TOKEN_CLOSE_TAG';
|
|
10
|
+
var TOKEN_SELF_TAG = 'TOKEN_SELF_TAG';
|
|
11
|
+
var TOKEN_TEXT = 'TOKEN_TEXT';
|
|
12
|
+
var NODE_FRAGMENT = 'NODE_FRAGMENT';
|
|
13
|
+
var NODE_TAG_ELEMENT = 'NODE_TAG_ELEMENT';
|
|
14
|
+
var NODE_VOID_ELEMENT = 'NODE_VOID_ELEMENT';
|
|
15
|
+
var NODE_PLACEHOLDER = 'NODE_PLACEHOLDER';
|
|
16
|
+
var NODE_TEXT = 'NODE_TEXT';
|
|
17
|
+
|
|
18
|
+
var _excluded = ["type", "children"];
|
|
19
|
+
var Node = /*#__PURE__*/function () {
|
|
20
|
+
function Node(_ref) {
|
|
21
|
+
var type = _ref.type,
|
|
22
|
+
children = _ref.children,
|
|
23
|
+
fields = _objectWithoutProperties(_ref, _excluded);
|
|
24
|
+
_classCallCheck(this, Node);
|
|
25
|
+
this.type = type;
|
|
26
|
+
this.children = children || [];
|
|
27
|
+
for (var key in fields) {
|
|
28
|
+
this[key] = fields[key];
|
|
29
|
+
}
|
|
30
|
+
if (fields.token) {
|
|
31
|
+
this.string = fields.token.string;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
_createClass(Node, [{
|
|
35
|
+
key: "appendChild",
|
|
36
|
+
value: function appendChild(child) {
|
|
37
|
+
this.children.push(child);
|
|
38
|
+
}
|
|
39
|
+
}, {
|
|
40
|
+
key: "isLeaf",
|
|
41
|
+
get: function get() {
|
|
42
|
+
return this.children.length === 0;
|
|
43
|
+
}
|
|
44
|
+
}]);
|
|
45
|
+
return Node;
|
|
46
|
+
}();
|
|
47
|
+
Node.createTagNode = function (token, children) {
|
|
48
|
+
return new Node({
|
|
49
|
+
type: NODE_TAG_ELEMENT,
|
|
50
|
+
children: children,
|
|
51
|
+
name: token.name,
|
|
52
|
+
token: token
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
Node.createFragmentNode = function (children) {
|
|
56
|
+
return new Node({
|
|
57
|
+
type: NODE_FRAGMENT,
|
|
58
|
+
children: children
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
Node.createVoidNode = function (token) {
|
|
62
|
+
return new Node({
|
|
63
|
+
type: NODE_VOID_ELEMENT,
|
|
64
|
+
name: token.name,
|
|
65
|
+
token: token
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
Node.createTextNode = function (token) {
|
|
69
|
+
return new Node({
|
|
70
|
+
type: NODE_TEXT,
|
|
71
|
+
text: token.string,
|
|
72
|
+
token: token
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
Node.createPlaceholderNode = function (token) {
|
|
76
|
+
return new Node({
|
|
77
|
+
type: NODE_PLACEHOLDER,
|
|
78
|
+
name: token.name,
|
|
79
|
+
token: token
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
var SYNTAX_BUILT_IN = [{
|
|
84
|
+
type: TOKEN_PLACEHOLDER,
|
|
85
|
+
regex: /{\s*(\w+)\s*}/g
|
|
86
|
+
}, {
|
|
87
|
+
type: TOKEN_OPEN_TAG,
|
|
88
|
+
regex: /<(\w+)>/g
|
|
89
|
+
}, {
|
|
90
|
+
type: TOKEN_CLOSE_TAG,
|
|
91
|
+
regex: /<\/(\w+)>/g
|
|
92
|
+
}, {
|
|
93
|
+
type: TOKEN_SELF_TAG,
|
|
94
|
+
regex: /<(\w+)\s*\/>/g
|
|
95
|
+
}];
|
|
96
|
+
var SYNTAX_I18NEXT = [{
|
|
97
|
+
type: TOKEN_PLACEHOLDER,
|
|
98
|
+
regex: /{{\s*(\w+)\s*}}/g
|
|
99
|
+
}, {
|
|
100
|
+
type: TOKEN_OPEN_TAG,
|
|
101
|
+
regex: /<(\w+)>/g
|
|
102
|
+
}, {
|
|
103
|
+
type: TOKEN_CLOSE_TAG,
|
|
104
|
+
regex: /<\/(\w+)>/g
|
|
105
|
+
}, {
|
|
106
|
+
type: TOKEN_SELF_TAG,
|
|
107
|
+
regex: /<(\w+)\s*\/>/g
|
|
108
|
+
}];
|
|
109
|
+
|
|
110
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
111
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
112
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; }
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* return a array of token object
|
|
116
|
+
*/
|
|
117
|
+
function lexer(string, syntax) {
|
|
118
|
+
var matches = [];
|
|
119
|
+
var _iterator = _createForOfIteratorHelper(syntax),
|
|
120
|
+
_step;
|
|
121
|
+
try {
|
|
122
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
123
|
+
var rule = _step.value;
|
|
124
|
+
var type = rule.type,
|
|
125
|
+
regex = rule.regex;
|
|
126
|
+
var res;
|
|
127
|
+
while ((res = regex.exec(string)) !== null) {
|
|
128
|
+
matches.push({
|
|
129
|
+
type: type,
|
|
130
|
+
string: res[0],
|
|
131
|
+
name: res[1],
|
|
132
|
+
start: res.index,
|
|
133
|
+
end: res.index + res[0].length
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (err) {
|
|
138
|
+
_iterator.e(err);
|
|
139
|
+
} finally {
|
|
140
|
+
_iterator.f();
|
|
141
|
+
}
|
|
142
|
+
matches.sort(function (a, b) {
|
|
143
|
+
return a.start - b.start;
|
|
144
|
+
});
|
|
145
|
+
var textTokens = [];
|
|
146
|
+
var start = 0;
|
|
147
|
+
matches.forEach(function (match) {
|
|
148
|
+
if (match.start === start) {
|
|
149
|
+
start = match.end;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
var end = match.start;
|
|
153
|
+
var text = string.substring(start, end);
|
|
154
|
+
textTokens.push({
|
|
155
|
+
type: TOKEN_TEXT,
|
|
156
|
+
string: text,
|
|
157
|
+
text: text,
|
|
158
|
+
start: start,
|
|
159
|
+
end: end
|
|
160
|
+
});
|
|
161
|
+
start = match.end;
|
|
162
|
+
});
|
|
163
|
+
var text = string.substring(start);
|
|
164
|
+
if (text !== '') {
|
|
165
|
+
textTokens.push({
|
|
166
|
+
type: TOKEN_TEXT,
|
|
167
|
+
string: text,
|
|
168
|
+
start: start,
|
|
169
|
+
end: string.length
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
var tokens = [].concat(textTokens, matches).sort(function (a, b) {
|
|
173
|
+
return a.start - b.start;
|
|
174
|
+
});
|
|
175
|
+
return tokens;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function parser(string, syntax) {
|
|
179
|
+
if (!syntax) {
|
|
180
|
+
syntax = SYNTAX_BUILT_IN;
|
|
181
|
+
}
|
|
182
|
+
var tokens = lexer(string, syntax);
|
|
183
|
+
var p = new Parser(tokens);
|
|
184
|
+
return p.parse();
|
|
185
|
+
}
|
|
186
|
+
var SYNTAX_ERROR = 'Syntax error. Please check if each open tag is closed correctly';
|
|
187
|
+
|
|
188
|
+
// A special token representing end of the tream
|
|
189
|
+
var EPSILON = {
|
|
190
|
+
type: 'EPSILON'
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/*
|
|
194
|
+
* A recursive descent parser that construct a syntax tree represeting
|
|
195
|
+
* the DOM hierarchy structure.
|
|
196
|
+
*
|
|
197
|
+
* For instance, the following token
|
|
198
|
+
* <h1>hi <b>{name}</b></h1>
|
|
199
|
+
*
|
|
200
|
+
* Would result in the following tree
|
|
201
|
+
*
|
|
202
|
+
* <h1>
|
|
203
|
+
* ├─ "hi"
|
|
204
|
+
* └─ <b>
|
|
205
|
+
* ├─ {name}
|
|
206
|
+
*
|
|
207
|
+
* The parser is based on the following grammar:
|
|
208
|
+
*
|
|
209
|
+
* document ::= elementOrData
|
|
210
|
+
* elementOrData ::= element elementOrData
|
|
211
|
+
* elementOrData ::= data elementOrData
|
|
212
|
+
* element ::= <open_tag> elementOrData <close_tag>
|
|
213
|
+
* data ::= <selfTag>
|
|
214
|
+
* data ::= <text>
|
|
215
|
+
* data ::= <placeholder>
|
|
216
|
+
*
|
|
217
|
+
* ref: https://github.com/amghannam/Mini-XML-Recursive-Descent-Parser
|
|
218
|
+
*/
|
|
219
|
+
var Parser = /*#__PURE__*/function () {
|
|
220
|
+
function Parser(tokens) {
|
|
221
|
+
_classCallCheck(this, Parser);
|
|
222
|
+
this.tokens = [].concat(tokens);
|
|
223
|
+
this.tags = [];
|
|
224
|
+
}
|
|
225
|
+
_createClass(Parser, [{
|
|
226
|
+
key: "parse",
|
|
227
|
+
value: function parse() {
|
|
228
|
+
var tree = this.document();
|
|
229
|
+
if (!this.predict(EPSILON.type)) {
|
|
230
|
+
throw new Error(SYNTAX_ERROR);
|
|
231
|
+
}
|
|
232
|
+
return tree;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/*
|
|
236
|
+
* @return {Node}
|
|
237
|
+
*/
|
|
238
|
+
}, {
|
|
239
|
+
key: "document",
|
|
240
|
+
value: function document() {
|
|
241
|
+
var children = this.elementOrData();
|
|
242
|
+
return Node.createFragmentNode(children);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/*
|
|
246
|
+
* @return {Node}
|
|
247
|
+
*/
|
|
248
|
+
}, {
|
|
249
|
+
key: "element",
|
|
250
|
+
value: function element() {
|
|
251
|
+
var tagToken = this.openTag();
|
|
252
|
+
var children = this.elementOrData();
|
|
253
|
+
this.endTag();
|
|
254
|
+
return Node.createTagNode(tagToken, children);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/*
|
|
258
|
+
* @return {Token}
|
|
259
|
+
*/
|
|
260
|
+
}, {
|
|
261
|
+
key: "openTag",
|
|
262
|
+
value: function openTag() {
|
|
263
|
+
if (!this.predict(TOKEN_OPEN_TAG)) {
|
|
264
|
+
throw new Error(SYNTAX_ERROR);
|
|
265
|
+
}
|
|
266
|
+
this.pushTag(this.lookahead);
|
|
267
|
+
return this.match(TOKEN_OPEN_TAG);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/*
|
|
271
|
+
* @return {[]Node}
|
|
272
|
+
*/
|
|
273
|
+
}, {
|
|
274
|
+
key: "elementOrData",
|
|
275
|
+
value: function elementOrData() {
|
|
276
|
+
var children = [];
|
|
277
|
+
if (this.predict(TOKEN_OPEN_TAG)) {
|
|
278
|
+
children.push(this.element());
|
|
279
|
+
children = children.concat(this.elementOrData());
|
|
280
|
+
}
|
|
281
|
+
if (this.predict(TOKEN_SELF_TAG, TOKEN_TEXT, TOKEN_PLACEHOLDER)) {
|
|
282
|
+
var token = this.match(this.lookahead.type);
|
|
283
|
+
var node;
|
|
284
|
+
switch (token.type) {
|
|
285
|
+
case TOKEN_SELF_TAG:
|
|
286
|
+
node = Node.createVoidNode(token);
|
|
287
|
+
break;
|
|
288
|
+
case TOKEN_TEXT:
|
|
289
|
+
node = Node.createTextNode(token);
|
|
290
|
+
break;
|
|
291
|
+
case TOKEN_PLACEHOLDER:
|
|
292
|
+
node = Node.createPlaceholderNode(token);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
children.push(node);
|
|
296
|
+
children = children.concat(this.elementOrData());
|
|
297
|
+
}
|
|
298
|
+
return children;
|
|
299
|
+
}
|
|
300
|
+
}, {
|
|
301
|
+
key: "endTag",
|
|
302
|
+
value: function endTag() {
|
|
303
|
+
if (!this.predict(TOKEN_CLOSE_TAG)) {
|
|
304
|
+
throw new Error(SYNTAX_ERROR);
|
|
305
|
+
}
|
|
306
|
+
var openTag = this.tags.pop();
|
|
307
|
+
if (openTag.name !== this.lookahead.name) {
|
|
308
|
+
throw new Error(SYNTAX_ERROR);
|
|
309
|
+
}
|
|
310
|
+
this.match(TOKEN_CLOSE_TAG);
|
|
311
|
+
}
|
|
312
|
+
}, {
|
|
313
|
+
key: "lookahead",
|
|
314
|
+
get: function get() {
|
|
315
|
+
return this.tokens.length === 0 ? EPSILON : this.tokens[0];
|
|
316
|
+
}
|
|
317
|
+
}, {
|
|
318
|
+
key: "predict",
|
|
319
|
+
value: function predict() {
|
|
320
|
+
for (var _len = arguments.length, types = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
321
|
+
types[_key] = arguments[_key];
|
|
322
|
+
}
|
|
323
|
+
return types.includes(this.lookahead.type);
|
|
324
|
+
}
|
|
325
|
+
}, {
|
|
326
|
+
key: "match",
|
|
327
|
+
value: function match(type) {
|
|
328
|
+
if (!this.predict(type)) {
|
|
329
|
+
throw new Error(SYNTAX_ERROR);
|
|
330
|
+
}
|
|
331
|
+
var token = this.tokens.shift();
|
|
332
|
+
return token;
|
|
333
|
+
}
|
|
334
|
+
}, {
|
|
335
|
+
key: "pushTag",
|
|
336
|
+
value: function pushTag(token) {
|
|
337
|
+
this.tags.push(token);
|
|
338
|
+
}
|
|
339
|
+
}]);
|
|
340
|
+
return Parser;
|
|
341
|
+
}();
|
|
342
|
+
|
|
343
|
+
var createElement = function createElement(node, mapping, keyPrefix) {
|
|
344
|
+
var children = node.children.map(function (c, i) {
|
|
345
|
+
return /*#__PURE__*/React.createElement(React.Fragment, {
|
|
346
|
+
key: keyPrefix + i
|
|
347
|
+
}, createElement(c, mapping, keyPrefix));
|
|
348
|
+
});
|
|
349
|
+
switch (node.type) {
|
|
350
|
+
case NODE_TEXT:
|
|
351
|
+
{
|
|
352
|
+
return node.text;
|
|
353
|
+
}
|
|
354
|
+
case NODE_FRAGMENT:
|
|
355
|
+
{
|
|
356
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
357
|
+
}
|
|
358
|
+
case NODE_VOID_ELEMENT:
|
|
359
|
+
{
|
|
360
|
+
var val = mapping[node.name];
|
|
361
|
+
if (typeof val === 'function') {
|
|
362
|
+
return val();
|
|
363
|
+
}
|
|
364
|
+
return val || /*#__PURE__*/React.createElement(node.name, null);
|
|
365
|
+
}
|
|
366
|
+
case NODE_TAG_ELEMENT:
|
|
367
|
+
{
|
|
368
|
+
var _val = mapping[node.name];
|
|
369
|
+
if (_val === undefined) {
|
|
370
|
+
return /*#__PURE__*/React.createElement(node.name, null, children);
|
|
371
|
+
}
|
|
372
|
+
if (typeof _val === 'function') {
|
|
373
|
+
return _val(children);
|
|
374
|
+
}
|
|
375
|
+
if (/*#__PURE__*/React.isValidElement(_val)) {
|
|
376
|
+
if (React.Children.count(_val.props.children) !== 0) {
|
|
377
|
+
throw new Error('when passing an element as value, the element should not contains children');
|
|
378
|
+
}
|
|
379
|
+
return /*#__PURE__*/React.cloneElement(_val, {
|
|
380
|
+
children: children
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
throw new Error("Invalid mapping value for \"".concat(node.name, "\". Only element or render function are accepted"));
|
|
384
|
+
}
|
|
385
|
+
case NODE_PLACEHOLDER:
|
|
386
|
+
{
|
|
387
|
+
var _val2 = mapping[node.name];
|
|
388
|
+
if (_val2 === undefined) {
|
|
389
|
+
console.warn("missing \"".concat(node.name, "\" in mapping"));
|
|
390
|
+
return node.string;
|
|
391
|
+
}
|
|
392
|
+
if (typeof _val2 === 'function') {
|
|
393
|
+
return _val2();
|
|
394
|
+
}
|
|
395
|
+
return _val2;
|
|
396
|
+
}
|
|
397
|
+
default:
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
function Interpolate(_ref) {
|
|
402
|
+
var string = _ref.string,
|
|
403
|
+
syntax = _ref.syntax,
|
|
404
|
+
_ref$mapping = _ref.mapping,
|
|
405
|
+
mapping = _ref$mapping === void 0 ? {} : _ref$mapping,
|
|
406
|
+
_ref$graceful = _ref.graceful,
|
|
407
|
+
graceful = _ref$graceful === void 0 ? true : _ref$graceful;
|
|
408
|
+
try {
|
|
409
|
+
var tree = parser(string, syntax);
|
|
410
|
+
return createElement(tree, mapping, string);
|
|
411
|
+
} catch (e) {
|
|
412
|
+
if (graceful) {
|
|
413
|
+
console.error(e);
|
|
414
|
+
return string;
|
|
415
|
+
} else {
|
|
416
|
+
throw e;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
Interpolate.propTypes = {
|
|
421
|
+
string: PropTypes.string.isRequired,
|
|
422
|
+
mapping: PropTypes.object,
|
|
423
|
+
graceful: PropTypes.bool
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
export { SYNTAX_BUILT_IN, SYNTAX_I18NEXT, TOKEN_CLOSE_TAG, TOKEN_OPEN_TAG, TOKEN_PLACEHOLDER, TOKEN_SELF_TAG, Interpolate as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@todoist/react-interpolate",
|
|
3
|
+
"version": "2.2.5",
|
|
4
|
+
"repository": "https://github.com/todoist/react-interpolate",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "A string interpolation component that formats and interpolates a template string in a safe way",
|
|
7
|
+
"main": "dist/react-interpolate.cjs",
|
|
8
|
+
"module": "dist/react-interpolate.mjs",
|
|
9
|
+
"types": "dist/react-interpolate.d.ts",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": "^20.0.0 || ^22.0.0 || ^24.0.0 || ^26.0.0",
|
|
12
|
+
"npm": "^10.0.0 || ^11.0.0 || ^12.0.0"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"lint": "eslint ./src ./__test__",
|
|
21
|
+
"build": "del dist && rollup -c && npm run mini-cjs && npm run mini-mjs",
|
|
22
|
+
"mini-cjs": "uglifyjs dist/react-interpolate.cjs --compress --mangle --enclose --output dist/react-interpolate.min.cjs",
|
|
23
|
+
"mini-mjs": "uglifyjs dist/react-interpolate.mjs --compress --mangle --enclose --output dist/react-interpolate.min.mjs",
|
|
24
|
+
"prettify": "prettier --write .",
|
|
25
|
+
"prepublishOnly": "node -e \"throw new Error('Use the reviewed retained-artifact publisher; see docs/releasing.md')\"",
|
|
26
|
+
"test:release": "node --test .github/scripts/*.test.mjs",
|
|
27
|
+
"test:package": "node .github/scripts/consumer-check.mjs"
|
|
28
|
+
},
|
|
29
|
+
"prettier": "@todoist/prettier-config",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"react",
|
|
32
|
+
"interpolate",
|
|
33
|
+
"template",
|
|
34
|
+
"format",
|
|
35
|
+
"text",
|
|
36
|
+
"string"
|
|
37
|
+
],
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"prop-types": "15.8.1",
|
|
40
|
+
"react": ">=17.0.2",
|
|
41
|
+
"react-dom": ">=17.0.2"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@babel/runtime": "7.18.6"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@babel/cli": "7.18.6",
|
|
48
|
+
"@babel/core": "7.29.6",
|
|
49
|
+
"@babel/eslint-parser": "7.18.2",
|
|
50
|
+
"@babel/plugin-transform-runtime": "7.18.6",
|
|
51
|
+
"@babel/preset-env": "7.18.6",
|
|
52
|
+
"@babel/preset-react": "7.18.6",
|
|
53
|
+
"@todoist/eslint-config": "13.1.2",
|
|
54
|
+
"@todoist/prettier-config": "4.0.2",
|
|
55
|
+
"@semantic-release/changelog": "6.0.3",
|
|
56
|
+
"@semantic-release/git": "10.0.1",
|
|
57
|
+
"@testing-library/react": "13.3.0",
|
|
58
|
+
"babel-jest": "28.1.2",
|
|
59
|
+
"conventional-changelog-conventionalcommits": "9.3.1",
|
|
60
|
+
"core-js": "3.23.3",
|
|
61
|
+
"del-cli": "4.0.1",
|
|
62
|
+
"eslint": "8.57.1",
|
|
63
|
+
"eslint-config-prettier": "10.1.8",
|
|
64
|
+
"eslint-plugin-compat": "4.0.2",
|
|
65
|
+
"eslint-plugin-import": "2.32.0",
|
|
66
|
+
"eslint-plugin-jest": "26.5.3",
|
|
67
|
+
"eslint-plugin-prettier": "5.5.4",
|
|
68
|
+
"eslint-plugin-react": "7.37.5",
|
|
69
|
+
"eslint-plugin-react-hooks": "7.0.1",
|
|
70
|
+
"gzip-cli": "1.2.0",
|
|
71
|
+
"jest": "28.1.2",
|
|
72
|
+
"jest-environment-jsdom": "28.1.2",
|
|
73
|
+
"prettier": "3.6.2",
|
|
74
|
+
"react": "18.2.0",
|
|
75
|
+
"react-dom": "18.2.0",
|
|
76
|
+
"rollup": "2.80.0",
|
|
77
|
+
"rollup-plugin-babel": "4.4.0",
|
|
78
|
+
"rollup-plugin-copy": "3.5.0",
|
|
79
|
+
"semantic-release": "25.0.5",
|
|
80
|
+
"uglify-es": "3.3.9"
|
|
81
|
+
}
|
|
82
|
+
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const TOKEN_PLACEHOLDER = 'TOKEN_PLACEHOLDER'
|
|
2
|
+
export const TOKEN_OPEN_TAG = 'TOKEN_OPEN_TAG'
|
|
3
|
+
export const TOKEN_CLOSE_TAG = 'TOKEN_CLOSE_TAG'
|
|
4
|
+
export const TOKEN_SELF_TAG = 'TOKEN_SELF_TAG'
|
|
5
|
+
export const TOKEN_TEXT = 'TOKEN_TEXT'
|
|
6
|
+
|
|
7
|
+
export const NODE_FRAGMENT = 'NODE_FRAGMENT'
|
|
8
|
+
export const NODE_TAG_ELEMENT = 'NODE_TAG_ELEMENT'
|
|
9
|
+
export const NODE_VOID_ELEMENT = 'NODE_VOID_ELEMENT'
|
|
10
|
+
export const NODE_PLACEHOLDER = 'NODE_PLACEHOLDER'
|
|
11
|
+
export const NODE_TEXT = 'NODE_TEXT'
|
package/src/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import parser from './parser'
|
|
4
|
+
import {
|
|
5
|
+
NODE_FRAGMENT,
|
|
6
|
+
NODE_TAG_ELEMENT,
|
|
7
|
+
NODE_VOID_ELEMENT,
|
|
8
|
+
NODE_PLACEHOLDER,
|
|
9
|
+
NODE_TEXT,
|
|
10
|
+
} from './constants'
|
|
11
|
+
|
|
12
|
+
const createElement = (node, mapping, keyPrefix) => {
|
|
13
|
+
const children = node.children.map((c, i) => (
|
|
14
|
+
<React.Fragment key={keyPrefix + i}>{createElement(c, mapping, keyPrefix)}</React.Fragment>
|
|
15
|
+
))
|
|
16
|
+
|
|
17
|
+
switch (node.type) {
|
|
18
|
+
case NODE_TEXT: {
|
|
19
|
+
return node.text
|
|
20
|
+
}
|
|
21
|
+
case NODE_FRAGMENT: {
|
|
22
|
+
return React.createElement(React.Fragment, null, children)
|
|
23
|
+
}
|
|
24
|
+
case NODE_VOID_ELEMENT: {
|
|
25
|
+
const val = mapping[node.name]
|
|
26
|
+
if (typeof val === 'function') {
|
|
27
|
+
return val()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return val || React.createElement(node.name, null)
|
|
31
|
+
}
|
|
32
|
+
case NODE_TAG_ELEMENT: {
|
|
33
|
+
const val = mapping[node.name]
|
|
34
|
+
|
|
35
|
+
if (val === undefined) {
|
|
36
|
+
return React.createElement(node.name, null, children)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof val === 'function') {
|
|
40
|
+
return val(children)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (React.isValidElement(val)) {
|
|
44
|
+
if (React.Children.count(val.props.children) !== 0) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'when passing an element as value, the element should not contains children',
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return React.cloneElement(val, { children })
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Invalid mapping value for "${node.name}". Only element or render function are accepted`,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
case NODE_PLACEHOLDER: {
|
|
58
|
+
const val = mapping[node.name]
|
|
59
|
+
if (val === undefined) {
|
|
60
|
+
console.warn(`missing "${node.name}" in mapping`)
|
|
61
|
+
return node.string
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (typeof val === 'function') {
|
|
65
|
+
return val()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return val
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default function Interpolate({ string, syntax, mapping = {}, graceful = true }) {
|
|
76
|
+
try {
|
|
77
|
+
const tree = parser(string, syntax)
|
|
78
|
+
return createElement(tree, mapping, string)
|
|
79
|
+
} catch (e) {
|
|
80
|
+
if (graceful) {
|
|
81
|
+
console.error(e)
|
|
82
|
+
return string
|
|
83
|
+
} else {
|
|
84
|
+
throw e
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Interpolate.propTypes = {
|
|
90
|
+
string: PropTypes.string.isRequired,
|
|
91
|
+
mapping: PropTypes.object,
|
|
92
|
+
graceful: PropTypes.bool,
|
|
93
|
+
}
|