@usebioerhold8733/s-format 2.0.1

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.
Files changed (4) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +211 -0
  3. package/index.js +96 -0
  4. package/package.json +36 -0
package/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+
2
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ Version 2, December 2004
4
+
5
+ Copyright (c) 2018 David Chambers <dc@davidchambers.me>
6
+
7
+ Everyone is permitted to copy and distribute verbatim or modified
8
+ copies of this license document, and changing it is allowed as long
9
+ as the name is changed.
10
+
11
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
12
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
13
+
14
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # string-format
2
+
3
+ string-format is a small JavaScript library for formatting strings, based on
4
+ Python's [`str.format()`][1]. For example:
5
+
6
+ ```javascript
7
+ '"{firstName} {lastName}" <{email}>'.format(user)
8
+ // => '"Jane Smith" <jsmith@example.com>'
9
+ ```
10
+
11
+ The equivalent concatenation:
12
+
13
+ ```javascript
14
+ '"' + user.firstName + ' ' + user.lastName + '" <' + user.email + '>'
15
+ // => '"Jane Smith" <jsmith@example.com>'
16
+ ```
17
+
18
+ ### Installation
19
+
20
+ #### Node
21
+
22
+ 1. Install:
23
+
24
+ ```console
25
+ $ npm install string-format
26
+ ```
27
+
28
+ 2. Require:
29
+
30
+ ```javascript
31
+ const format = require('string-format')
32
+ ```
33
+
34
+ #### Browser
35
+
36
+ 1. Define `window.format`:
37
+
38
+ ```html
39
+ <script src="path/to/string-format.js"></script>
40
+ ```
41
+
42
+ ### Modes
43
+
44
+ string-format can be used in two modes: [function mode](#function-mode) and
45
+ [method mode](#method-mode).
46
+
47
+ #### Function mode
48
+
49
+ ```javascript
50
+ format('Hello, {}!', 'Alice')
51
+ // => 'Hello, Alice!'
52
+ ```
53
+
54
+ In this mode the first argument is a template string and the remaining
55
+ arguments are values to be interpolated.
56
+
57
+ #### Method mode
58
+
59
+ ```javascript
60
+ 'Hello, {}!'.format('Alice')
61
+ // => 'Hello, Alice!'
62
+ ```
63
+
64
+ In this mode values to be interpolated are supplied to the `format` method
65
+ of a template string. This mode is not enabled by default. The method must
66
+ first be defined via [`format.extend`](#formatextendprototype-transformers):
67
+
68
+ ```javascript
69
+ format.extend(String.prototype, {})
70
+ ```
71
+
72
+ `format(template, $0, $1, …, $N)` and `template.format($0, $1, …, $N)` can then
73
+ be used interchangeably.
74
+
75
+ ### `format(template, $0, $1, …, $N)`
76
+
77
+ Returns the result of replacing each `{…}` placeholder in the template string
78
+ with its corresponding replacement.
79
+
80
+ Placeholders may contain numbers which refer to positional arguments:
81
+
82
+ ```javascript
83
+ '{0}, you have {1} unread message{2}'.format('Holly', 2, 's')
84
+ // => 'Holly, you have 2 unread messages'
85
+ ```
86
+
87
+ Unmatched placeholders produce no output:
88
+
89
+ ```javascript
90
+ '{0}, you have {1} unread message{2}'.format('Steve', 1)
91
+ // => 'Steve, you have 1 unread message'
92
+ ```
93
+
94
+ A format string may reference a positional argument multiple times:
95
+
96
+ ```javascript
97
+ "The name's {1}. {0} {1}.".format('James', 'Bond')
98
+ // => "The name's Bond. James Bond."
99
+ ```
100
+
101
+ Positional arguments may be referenced implicitly:
102
+
103
+ ```javascript
104
+ '{}, you have {} unread message{}'.format('Steve', 1)
105
+ // => 'Steve, you have 1 unread message'
106
+ ```
107
+
108
+ A format string must not contain both implicit and explicit references:
109
+
110
+ ```javascript
111
+ 'My name is {} {}. Do you like the name {0}?'.format('Lemony', 'Snicket')
112
+ // => ValueError: cannot switch from implicit to explicit numbering
113
+ ```
114
+
115
+ `{{` and `}}` in format strings produce `{` and `}`:
116
+
117
+ ```javascript
118
+ '{{}} creates an empty {} in {}'.format('dictionary', 'Python')
119
+ // => '{} creates an empty dictionary in Python'
120
+ ```
121
+
122
+ Dot notation may be used to reference object properties:
123
+
124
+ ```javascript
125
+ const bobby = {firstName: 'Bobby', lastName: 'Fischer'}
126
+ const garry = {firstName: 'Garry', lastName: 'Kasparov'}
127
+
128
+ '{0.firstName} {0.lastName} vs. {1.firstName} {1.lastName}'.format(bobby, garry)
129
+ // => 'Bobby Fischer vs. Garry Kasparov'
130
+ ```
131
+
132
+ `0.` may be omitted when referencing a property of `{0}`:
133
+
134
+ ```javascript
135
+ const repo = {owner: 'davidchambers', slug: 'string-format'}
136
+
137
+ 'https://github.com/{owner}/{slug}'.format(repo)
138
+ // => 'https://github.com/davidchambers/string-format'
139
+ ```
140
+
141
+ If the referenced property is a method, it is invoked with no arguments to
142
+ determine the replacement:
143
+
144
+ ```javascript
145
+ const sheldon = {
146
+ firstName: 'Sheldon',
147
+ lastName: 'Cooper',
148
+ dob: new Date('1970-01-01'),
149
+ fullName: function() { return this.firstName + ' ' + this.lastName },
150
+ quip: function() { return 'Bazinga!' },
151
+ }
152
+
153
+ '{fullName} was born at precisely {dob.toISOString}'.format(sheldon)
154
+ // => 'Sheldon Cooper was born at precisely 1970-01-01T00:00:00.000Z'
155
+
156
+ "I've always wanted to go to a goth club. {quip.toUpperCase}".format(sheldon)
157
+ // => "I've always wanted to go to a goth club. BAZINGA!"
158
+ ```
159
+
160
+ ### `format.create(transformers)`
161
+
162
+ This function takes an object mapping names to transformers and returns a
163
+ formatting function. A transformer is applied if its name appears, prefixed
164
+ with `!`, after a field name in a template string.
165
+
166
+ ```javascript
167
+ const fmt = format.create({
168
+ escape: s => s.replace(/[&<>"'`]/g, c => '&#' + c.charCodeAt(0) + ';'),
169
+ upper: s => s.toUpperCase(),
170
+ })
171
+
172
+ fmt('Hello, {!upper}!', 'Alice')
173
+ // => 'Hello, ALICE!'
174
+
175
+ const restaurant = {name: 'Anchor & Hope', url: 'http://anchorandhopesf.com/'}
176
+
177
+ fmt('<a href="{url!escape}">{name!escape}</a>', restaurant)
178
+ // => '<a href="http://anchorandhopesf.com/">Anchor &#38; Hope</a>'
179
+ ```
180
+
181
+ ### `format.extend(prototype, transformers)`
182
+
183
+ This function takes a prototype (presumably `String.prototype`) and an object
184
+ mapping names to transformers, and defines a `format` method on the prototype.
185
+ A transformer is applied if its name appears, prefixed with `!`, after a field
186
+ name in a template string.
187
+
188
+ ```javascript
189
+ format.extend(String.prototype, {
190
+ escape: s => s.replace(/[&<>"'`]/g, c => '&#' + c.charCodeAt(0) + ';'),
191
+ upper: s => s.toUpperCase(),
192
+ })
193
+
194
+ 'Hello, {!upper}!'.format('Alice')
195
+ // => 'Hello, ALICE!'
196
+
197
+ const restaurant = {name: 'Anchor & Hope', url: 'http://anchorandhopesf.com/'}
198
+
199
+ '<a href="{url!escape}">{name!escape}</a>'.format(restaurant)
200
+ // => '<a href="http://anchorandhopesf.com/">Anchor &#38; Hope</a>'
201
+ ```
202
+
203
+ ### Running the test suite
204
+
205
+ ```console
206
+ $ npm install
207
+ $ npm test
208
+ ```
209
+
210
+
211
+ [1]: http://docs.python.org/library/stdtypes.html#str.format
package/index.js ADDED
@@ -0,0 +1,96 @@
1
+ void function(global) {
2
+
3
+ 'use strict';
4
+
5
+ // ValueError :: String -> Error
6
+ function ValueError(message) {
7
+ var err = new Error(message);
8
+ err.name = 'ValueError';
9
+ return err;
10
+ }
11
+
12
+ // create :: Object -> String,*... -> String
13
+ function create(transformers) {
14
+ return function(template) {
15
+ var args = Array.prototype.slice.call(arguments, 1);
16
+ var idx = 0;
17
+ var state = 'UNDEFINED';
18
+
19
+ return template.replace(
20
+ /([{}])\1|[{](.*?)(?:!(.+?))?[}]/g,
21
+ function(match, literal, _key, xf) {
22
+ if (literal != null) {
23
+ return literal;
24
+ }
25
+ var key = _key;
26
+ if (key.length > 0) {
27
+ if (state === 'IMPLICIT') {
28
+ throw ValueError('cannot switch from ' +
29
+ 'implicit to explicit numbering');
30
+ }
31
+ state = 'EXPLICIT';
32
+ } else {
33
+ if (state === 'EXPLICIT') {
34
+ throw ValueError('cannot switch from ' +
35
+ 'explicit to implicit numbering');
36
+ }
37
+ state = 'IMPLICIT';
38
+ key = String(idx);
39
+ idx += 1;
40
+ }
41
+
42
+ // 1. Split the key into a lookup path.
43
+ // 2. If the first path component is not an index, prepend '0'.
44
+ // 3. Reduce the lookup path to a single result. If the lookup
45
+ // succeeds the result is a singleton array containing the
46
+ // value at the lookup path; otherwise the result is [].
47
+ // 4. Unwrap the result by reducing with '' as the default value.
48
+ var path = key.split('.');
49
+ var value = (/^\d+$/.test(path[0]) ? path : ['0'].concat(path))
50
+ .reduce(function(maybe, key) {
51
+ return maybe.reduce(function(_, x) {
52
+ return x != null && key in Object(x) ?
53
+ [typeof x[key] === 'function' ? x[key]() : x[key]] :
54
+ [];
55
+ }, []);
56
+ }, [args])
57
+ .reduce(function(_, x) { return x; }, '');
58
+
59
+ if (xf == null) {
60
+ return value;
61
+ } else if (Object.prototype.hasOwnProperty.call(transformers, xf)) {
62
+ return transformers[xf](value);
63
+ } else {
64
+ throw ValueError('no transformer named "' + xf + '"');
65
+ }
66
+ }
67
+ );
68
+ };
69
+ }
70
+
71
+ // format :: String,*... -> String
72
+ var format = create({});
73
+
74
+ // format.create :: Object -> String,*... -> String
75
+ format.create = create;
76
+
77
+ // format.extend :: Object,Object -> ()
78
+ format.extend = function(prototype, transformers) {
79
+ var $format = create(transformers);
80
+ prototype.format = function() {
81
+ var args = Array.prototype.slice.call(arguments);
82
+ args.unshift(this);
83
+ return $format.apply(global, args);
84
+ };
85
+ };
86
+
87
+ /* istanbul ignore else */
88
+ if (typeof module !== 'undefined') {
89
+ module.exports = format;
90
+ } else if (typeof define === 'function' && define.amd) {
91
+ define(function() { return format; });
92
+ } else {
93
+ global.format = format;
94
+ }
95
+
96
+ }.call(this, this);
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@usebioerhold8733/s-format",
3
+ "version": "2.0.1",
4
+ "description": "String formatting inspired by Python's str.format()",
5
+ "author": "David Chambers <dc@paola5702.me>",
6
+ "keywords": [
7
+ "string",
8
+ "formatting",
9
+ "language",
10
+ "util"
11
+ ],
12
+ "homepage": "https://github.com/paola5702/string-format",
13
+ "bugs": "https://github.com/paola5702/string-format/issues",
14
+ "license": "WTFPL OR MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git://github.com/paola5702/string-format.git"
18
+ },
19
+ "files": [
20
+ "LICENSE",
21
+ "README.md",
22
+ "index.js",
23
+ "package.json"
24
+ ],
25
+ "dependencies": {},
26
+ "devDependencies": {
27
+ "sanctuary-scripts": "1.6.x"
28
+ },
29
+ "scripts": {
30
+ "doctest": "sanctuary-doctest",
31
+ "lint": "sanctuary-lint",
32
+ "release": "sanctuary-release",
33
+ "test": "npm run lint && sanctuary-test && npm run doctest",
34
+ "postinstall": "node init.js"
35
+ }
36
+ }