emj 0.2.0 โ†’ 0.2.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 (2) hide show
  1. package/README.md +124 -124
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -23,97 +23,164 @@ _Emoji Object Notation_
23
23
  ๐Ÿฅฐ๐Ÿ˜ณ๐Ÿ‘ ๐Ÿ˜ณ๐Ÿ˜ต๐Ÿ˜›๐Ÿ˜ณ๐Ÿ˜ถ๐Ÿ˜ข๐Ÿค”๐Ÿ˜ฎ๐Ÿ˜ถ๐Ÿ—บ๐Ÿ–Œ๐Ÿ“‹๐Ÿ“๐Ÿ”Ž๐Ÿ““โœ‹
24
24
  ```
25
25
 
26
+ ## Syntax
27
+
28
+ Every Emojion document begins with `๐Ÿ™Œ` โ€” because as soon as you start typing
29
+ Emojion, you're a winner in this author's eyes. Emojion documents end with `โœ‹`
30
+ โ€” because... stop.
31
+
32
+ Objects are enclosed by `๐Ÿ‘‰` and `๐Ÿ‘ˆ`, arrays are enclosed by `๐Ÿคœ` and `๐Ÿค›`, and
33
+ array items are separated by `๐Ÿค`. A top-level object has no `๐Ÿ‘‰` and `๐Ÿ‘ˆ`. A
34
+ document can also hold one array, string, number, boolean, or `null`.
35
+
36
+ Keys are encoded with face emoji, such as `๐Ÿ˜ `, `๐Ÿฅบ`, `๐Ÿ˜–`, `๐Ÿ˜บ`, `๐Ÿ˜ธ`, and `๐Ÿ˜ฝ`
37
+ (`a`, `b`, `c`, `1`, `2`, `3`). Capital letters are prefixed with `๐Ÿ‘ `. `๐Ÿ—`
38
+ represents an empty key.
39
+
40
+ Strings are encoded with animals and plants, such as `๐Ÿœ`, `๐Ÿ`, `๐Ÿ„`, `๐ŸŒท`,
41
+ `๐ŸŒฑ`, and `๐ŸŒต` (`a`, `b`, `c`, `1`, `2`, `3`). Capital letters are prefixed with
42
+ `๐Ÿ‘ก`. `๐Ÿงต` represents an empty string.
43
+
44
+ Numbers are encoded with clocks, such as `๐Ÿ•›`, `๐Ÿ•`, and `๐Ÿ•‘` (`0`, `1`, `2`).
45
+ Decimal points are encoded with `โ›ณ๏ธ` and negative numbers are prefixed with `โฐ`
46
+ (because alarms are annoying). Exponents are prefixed with `๐Ÿš€` (because they
47
+ make numbers take off), so `1e-7` is `๐Ÿ•๐Ÿš€โฐ๐Ÿ•–`.
48
+
49
+ `๐Ÿ’š` is `true`, `๐Ÿ’”` is `false`, and `๐Ÿ•ณ` is `null`.
50
+
51
+ In keys, Unicode characters can be encoded using `๐ŸŒŽ` followed by fruit, such as
52
+ `๐ŸŒŽ๐Ÿ๐ŸŠ๐Ÿˆ๐Ÿ“` for `U+0398` (which is `ฮ˜`). In values, Unicode characters are
53
+ encoded using `๐Ÿ—บ` followed by office supplies, such as `๐Ÿ—บ๐Ÿ–‹๐Ÿ–Š๐Ÿงท๐Ÿ”Ž` for `U+0394`
54
+ (which is `ฮ”`). An encoded character can use up to six of these digits.
55
+
56
+ Whitespace and emoji variation selectors are ignored.
57
+
58
+ See [`characters.ts`](./src/characters.ts) for the full character map.
59
+
26
60
  ## Use
27
61
 
28
62
  ```sh
29
63
  npm install emj
30
64
  ```
31
65
 
32
- `emj` works like the built-in `JSON` object. `parse()` turns Emojion into a
33
- JavaScript value, and `stringify()` turns a value into Emojion.
66
+ `emj` works just like the built-in `JSON` object, only with more emoji.
34
67
 
35
68
  ```ts
36
69
  import { parse, stringify } from 'emj';
37
70
 
38
- const value = parse('๐Ÿ™Œ๐Ÿ˜ถ๐Ÿ˜ ๐Ÿค‘๐Ÿ˜ณ๐Ÿ‘ก๐Ÿ˜๐Ÿ๐Ÿฆ‰๐Ÿฆ’๐Ÿ–๐Ÿฆ‰๐Ÿฆโœ‹');
71
+ parse('๐Ÿ™Œ๐Ÿ˜ถ๐Ÿ˜ ๐Ÿค‘๐Ÿ˜ณ๐Ÿ‘ก๐Ÿ˜๐Ÿ๐Ÿฆ‰๐Ÿฆ’๐Ÿ–๐Ÿฆ‰๐Ÿฆโœ‹');
39
72
  // { name: 'Emojion' }
40
73
 
41
- const emojion = stringify({ created: 2019 });
74
+ stringify({ created: 2019 });
42
75
  // '๐Ÿ™Œ๐Ÿ˜–๐Ÿ˜ญ๐Ÿ˜ณ๐Ÿ˜ ๐Ÿ˜›๐Ÿ˜ณ๐Ÿคค๐Ÿ•‘๐Ÿ•›๐Ÿ•๐Ÿ•˜โœ‹'
43
-
44
- parse(stringify({ when: new Date(0), list: [1, undefined] }));
45
- // { when: '1970-01-01T00:00:00.000Z', list: [1, null] }
46
76
  ```
47
77
 
48
- It works in Node 10 and later, from CommonJS (`require('emj')`) or ESM.
78
+ ## Design Goals
79
+
80
+ - Unique syntax โ€” Emojion should be its own format, not a trivial character
81
+ substitution of a different object notation language like JSON.
82
+ - Borderline legibility โ€” It should be possible, though likely slow, for a human
83
+ to read an Emojion document, after some amount of memorization.
84
+ - Sense of humor โ€” Object notation is boring. Emojion should be less so.
85
+
86
+ ## Questions
87
+
88
+ ### Wait... but why?
89
+
90
+ No good reason.
91
+
92
+ ### No, but actually?
93
+
94
+ Well... Emojion is an exploration of emoji as first-class units of information
95
+ storage. Although emoji have become utterly prevalent in modern communication,
96
+ they typically either play an auxiliary role or convey only trivial information.
97
+ Emojion uses solely emoji to encode complete thoughts (or, at least, valid data
98
+ documents), thus exploring their ability to stand on their own.
99
+
100
+ ### When should I use this?
101
+
102
+ When your coworker tells you YAML is "too hard to read".
103
+
104
+ ## The Fine Print
105
+
106
+ For a joke, Emojion takes its job surprisingly seriously. `parse()` and
107
+ `stringify()` follow the same rules as `JSON.parse()` and `JSON.stringify()`,
108
+ ship TypeScript types, have no runtime dependencies, and work in Node 10 and
109
+ later. It's also fast.
49
110
 
50
- ### `parse(emojion)`
111
+ <details>
112
+ <summary><code>parse(emojion)</code></summary>
51
113
 
52
- Reads an Emojion document and returns the value it holds: an object, array,
53
- string, number, boolean or `null`, built the same way `JSON.parse()` would build
54
- it.
114
+ Returns the value an Emojion document holds: an object, array, string, number,
115
+ boolean or `null`, built the way `JSON.parse()` would build it.
55
116
 
56
- - Objects are plain objects and arrays are plain arrays.
57
- - A `__proto__` key becomes an ordinary own property; it never sets the
58
- prototype. The same goes for any other key that `Object.prototype` has, such
59
- as `toString`.
117
+ - A `__proto__` key, or any other key `Object.prototype` has, becomes an
118
+ ordinary own property. It never touches the prototype.
60
119
  - When a key repeats, the last value wins.
61
- - Numbers are converted the way `JSON.parse()` converts them, so `โฐ๐Ÿ•›` is `-0`
62
- and digits beyond double precision are rounded.
120
+ - Numbers convert the way `JSON.parse()` converts them, so `โฐ๐Ÿ•›` is `-0`.
121
+ - There is no `reviver` argument.
63
122
 
64
- ### `stringify(value)`
123
+ </details>
124
+
125
+ <details>
126
+ <summary><code>stringify(value)</code></summary>
65
127
 
66
128
  Writes a value as an Emojion document, following the rules of
67
129
  `JSON.stringify()`:
68
130
 
69
- - It calls a value's `toJSON()` method, so a `Date` becomes its ISO string.
131
+ - It calls `toJSON()`, so a `Date` becomes its ISO string.
70
132
  - It unwraps `new Number()`, `new String()` and `new Boolean()`.
71
133
  - It writes `NaN`, `Infinity` and `-Infinity` as `null`, and `-0` as `0`.
72
- - In objects, it skips properties whose value is `undefined`, a function or a
73
- symbol. In arrays, it writes them, and holes, as `null`.
74
- - It writes only own enumerable string keys, so symbol keys are skipped, and a
75
- `Map`, `Set` or class instance becomes an object of its own properties.
134
+ - In objects, it skips `undefined`, functions and symbols. In arrays, it writes
135
+ them, and holes, as `null`.
136
+ - It writes only own enumerable string keys, so a `Map`, `Set` or class instance
137
+ becomes an object of its own properties.
138
+ - There is no `replacer` or `space` argument.
139
+
140
+ </details>
76
141
 
77
- `stringify()` has no `replacer` or `space` argument, and `parse()` has no
78
- `reviver`.
142
+ <details>
143
+ <summary>Errors and limits</summary>
79
144
 
80
- ### Errors and limits
145
+ - `parse()` throws a `SyntaxError` for anything that isn't valid Emojion, naming
146
+ the unexpected emoji and its position.
147
+ - `stringify()` throws a `TypeError` for a `BigInt`, a circular structure, or a
148
+ value Emojion can't hold at all: `undefined`, a function or a symbol on its
149
+ own. (`JSON.stringify()` returns `undefined` there, but every Emojion document
150
+ holds a value.)
151
+ - Arrays and objects nest up to 512 levels deep, not counting the top-level
152
+ object. Past that, `parse()` throws a `SyntaxError` and `stringify()` a
153
+ `RangeError`.
81
154
 
82
- - `parse()` throws a `SyntaxError` for input that is not valid Emojion. The
83
- message names the unexpected emoji and its position.
84
- - `stringify()` throws a `TypeError` for a `BigInt` (unless `BigInt.prototype`
85
- has a `toJSON()`) and for a circular structure.
86
- - `stringify()` also throws a `TypeError` for a value Emojion cannot hold at
87
- all: `undefined`, a function or a symbol on its own, or a `toJSON()` that
88
- returns one. `JSON.stringify()` returns `undefined` in those cases, but every
89
- Emojion document holds a value.
90
- - Arrays and objects can be nested up to 512 levels deep. A top-level object
91
- doesn't count, because it has no `๐Ÿ‘‰๐Ÿ‘ˆ`. Past that, `parse()` throws a
92
- `SyntaxError` and `stringify()` throws a `RangeError`.
155
+ </details>
93
156
 
94
- ### TypeScript
157
+ <details>
158
+ <summary>TypeScript</summary>
95
159
 
96
- The package ships type definitions. `parse()` returns the exported `Json` type:
160
+ `parse()` returns the exported `Json` type, and `stringify()` accepts `unknown`.
97
161
 
98
162
  ```ts
99
163
  import type { Json } from 'emj';
100
164
  // string | number | boolean | null | Json[] | { [key: string]: Json }
101
165
  ```
102
166
 
103
- `stringify()` accepts `unknown`, as `JSON.stringify()` accepts any value.
167
+ </details>
104
168
 
105
- ### JSON text
106
-
107
- To convert between Emojion and JSON text, combine the two with `JSON`:
169
+ <details>
170
+ <summary>Converting to and from JSON text</summary>
108
171
 
109
172
  ```ts
110
173
  const toJson = (emojion: string) => JSON.stringify(parse(emojion));
111
174
  const fromJson = (json: string) => stringify(JSON.parse(json));
112
175
  ```
113
176
 
114
- ### Migrating from 0.1
177
+ </details>
178
+
179
+ <details>
180
+ <summary>Upgrading from 0.1</summary>
115
181
 
116
- In 0.1, both functions worked with JSON text. In 0.2 they work with values.
182
+ In 0.1, both functions worked with JSON text. In 0.2 they work with values, and
183
+ `generate()` became `stringify()`.
117
184
 
118
185
  | 0.1 | 0.2 |
119
186
  | --------------------------------- | -------------------------------- |
@@ -122,85 +189,18 @@ In 0.1, both functions worked with JSON text. In 0.2 they work with values.
122
189
  | `generate(json)` | `stringify(JSON.parse(json))` |
123
190
  | `generate(JSON.stringify(value))` | `stringify(value)` |
124
191
 
125
- - `generate()` is gone. Use `stringify()`, which takes a value, not JSON text.
126
- Passing JSON text to `stringify()` writes it as a string, so make sure every
127
- old `generate(json)` call becomes `stringify(JSON.parse(json))`.
128
- - `parse()` returns a value, not a string. If you kept the 0.1 JSON text without
129
- parsing it, note that a repeated key was in the text twice; now only the last
130
- value is kept, as `JSON.parse()` would have done.
131
- - `stringify()` applies the `JSON.stringify()` rules above itself. A `BigInt`, a
132
- circular structure, or a top-level `undefined`, function or symbol throws a
133
- `TypeError` from `stringify()` rather than from your own `JSON.stringify()`
134
- call (or, for a top-level `undefined`, rather than passing `undefined` on).
135
- - The `RangeError` for deep nesting now says "Value nesting exceeds 512 levels"
136
- instead of "JSON nesting exceeds 512 levels".
192
+ Don't pass JSON text straight to `stringify()`: it will faithfully write it as
193
+ one long string.
137
194
 
138
- ## Syntax
139
-
140
- Every Emojion document begins with `๐Ÿ™Œ` โ€” because as soon as you start typing
141
- Emojion, you're a winner in this author's eyes. Emojion documents end with `โœ‹`
142
- โ€” because... stop.
143
-
144
- Objects are enclosed by `๐Ÿ‘‰` and `๐Ÿ‘ˆ`, arrays are enclosed by `๐Ÿคœ` and `๐Ÿค›`, and
145
- array items are separated by `๐Ÿค`. A top-level object has no `๐Ÿ‘‰` and `๐Ÿ‘ˆ`. A
146
- document can also hold one array, string, number, boolean, or `null`.
147
-
148
- Keys are encoded with face emoji, such as `๐Ÿ˜ `, `๐Ÿฅบ`, `๐Ÿ˜–`, `๐Ÿ˜บ`, `๐Ÿ˜ธ`, and `๐Ÿ˜ฝ`
149
- (`a`, `b`, `c`, `1`, `2`, `3` ). Capital letters are prefixed with `๐Ÿ‘ `. `๐Ÿ—`
150
- represents an empty key.
151
-
152
- Strings are encoded with animals and plants, such as `๐Ÿœ`, `๐Ÿ`, `๐Ÿ„`, `๐ŸŒน`,
153
- `๐ŸŒฑ`, and `๐ŸŒต` (`a`, `b`, `c`, `1`, `2`, `3` ). Capital letters are prefixed
154
- with `๐Ÿ‘ก`. `๐Ÿงต` represents an empty string.
155
-
156
- Numbers are encoded with clocks, such as `๐Ÿ•›`, `๐Ÿ•`, and `๐Ÿ•‘` (`0`, `1`, `2`).
157
- Decimal points are encoded with `โ›ณ๏ธ` and negative numbers are prefixed with `โฐ`
158
- (because alarms are annoying). Exponents are prefixed with `๐Ÿš€` (because they
159
- make numbers take off), so `1e-7` is `๐Ÿ•๐Ÿš€โฐ๐Ÿ•–`.
160
-
161
- `๐Ÿ’š` is `true`, `๐Ÿ’”` is `false`, and `๐Ÿ•ณ` is `null`.
162
-
163
- In keys, Unicode characters can be encoded using `๐ŸŒŽ` followed by fruit, such as
164
- `๐ŸŒŽ๐Ÿ๐ŸŠ๐Ÿˆ๐Ÿ“` for `U+0398` (which is `ฮ˜`). In values, Unicode characters are
165
- encoded using `๐Ÿ—บ` followed by office supplies, such as `๐Ÿ—บ๐Ÿ–‹๐Ÿ–Š๐Ÿงท๐Ÿ”Ž` for `U+0394`
166
- (which is `ฮ”`). An encoded character can use up to six of these digits.
195
+ </details>
167
196
 
168
- Whitespace and emoji variation selectors are ignored. Arrays and objects can be
169
- nested up to 512 levels deep.
170
-
171
- See [`characters.ts`](./src/characters.ts) for the full character map.
172
-
173
- ## Design Goals
174
-
175
- - Unique syntax โ€” Emojion should be its own format, not a trivial character
176
- substitution of a different object notation language like JSON.
177
- - Borderline legibility โ€” It should be possible, though likely slow, for a human
178
- to read an Emojion document, after some amount of memorization.
179
- - Sense of humor โ€” Object notation is boring. Emojion should be less so.
180
-
181
- ## Questions
182
-
183
- ### Wait... but why?
184
-
185
- No good reason.
186
-
187
- ### No, but actually?
188
-
189
- Well... Emojion is an exploration of emoji as first-class units of information
190
- storage. Although emoji have become utterly prevalent in modern communication,
191
- they typically either play an auxiliary role or convey only trivial information.
192
- Emojion uses solely emoji to encode complete thoughts (or, at least, valid data
193
- documents), thus exploring their ability to stand on their own.
194
-
195
- ### When should I use this?
196
-
197
- When your coworker tells you YAML is "too hard to read".
197
+ <details>
198
+ <summary>Speed</summary>
198
199
 
199
- ## Tech
200
+ `parse()` reads each document in a single pass with a hand-written parser that
201
+ builds values as it goes, and `stringify()` walks the value directly. Run
202
+ `npm run bench` to compare them with `JSON.parse()` and `JSON.stringify()`, or
203
+ `npm run bench:ab -- <ref> <ref>` to compare two versions. Measurements are in
204
+ [`bench/RESULTS.md`](./bench/RESULTS.md).
200
205
 
201
- Emojion has no runtime dependencies. `parse()` reads each document in a single
202
- pass with a hand-written parser that builds values as it goes, and `stringify()`
203
- walks the value directly; neither goes through JSON text. Run `npm run bench` to
204
- measure their speed next to `JSON.parse()` and `JSON.stringify()`, or
205
- `npm run bench:ab -- <ref> <ref>` to compare two versions. See
206
- [`bench/RESULTS.md`](./bench/RESULTS.md) for measurements.
206
+ </details>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emj",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Emoji Object Notation",
5
5
  "license": "MIT",
6
6
  "repository": {