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.
- package/README.md +124 -124
- 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
|
|
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
|
-
|
|
71
|
+
parse('๐๐ถ๐ ๐ค๐ณ๐ก๐๐๐ฆ๐ฆ๐๐ฆ๐ฆโ');
|
|
39
72
|
// { name: 'Emojion' }
|
|
40
73
|
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
|
|
111
|
+
<details>
|
|
112
|
+
<summary><code>parse(emojion)</code></summary>
|
|
51
113
|
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
-
|
|
57
|
-
|
|
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
|
|
62
|
-
|
|
120
|
+
- Numbers convert the way `JSON.parse()` converts them, so `โฐ๐` is `-0`.
|
|
121
|
+
- There is no `reviver` argument.
|
|
63
122
|
|
|
64
|
-
|
|
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
|
|
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
|
|
73
|
-
|
|
74
|
-
- It writes only own enumerable string keys, so
|
|
75
|
-
|
|
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
|
-
|
|
78
|
-
|
|
142
|
+
<details>
|
|
143
|
+
<summary>Errors and limits</summary>
|
|
79
144
|
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
157
|
+
<details>
|
|
158
|
+
<summary>TypeScript</summary>
|
|
95
159
|
|
|
96
|
-
|
|
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
|
-
|
|
167
|
+
</details>
|
|
104
168
|
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
169
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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>
|