1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// based on https://github.com/microsoft/TypeScript/tree/master/scripts/regenerate-unicode-identifier-parts.js
/** @param {number} i */
function toHex4Digits(i) {
let s = i.toString(16);
while (s.length < 4) {
s = '0' + s;
}
if (s.length > 4) throw new Error('Invalid Hex4Digits value');
return s;
}
class NonSurrogateRange {
/** @param {number} codePoint */
constructor(codePoint) {
this.firstCodePoint = codePoint;
this.lastCodePoint = codePoint;
}
toString() {
let text = '\\u' + toHex4Digits(this.firstCodePoint);
if (this.lastCodePoint !== this.firstCodePoint) {
text += '-\\u' + toHex4Digits(this.lastCodePoint);
}
return text;
}
}
class LeadSurrogateRange {
/** @param {number} leadSurrogate */
constructor(leadSurrogate) {
this.leadSurrogate = leadSurrogate;
/** @type {TrailSurrogateRange[]} */
this.ranges = [];
}
toString() {
return (
'\\u' +
toHex4Digits(this.leadSurrogate) +
'[' +
this.ranges.join('') +
']'
);
}
}
class TrailSurrogateRange {
/** @param {number} trailSurrogate */
constructor(trailSurrogate) {
this.firstTrailSurrogate = trailSurrogate;
this.lastTrailSurrogate = trailSurrogate;
}
toString() {
let text = '\\u' + toHex4Digits(this.firstTrailSurrogate);
if (this.lastTrailSurrogate !== this.firstTrailSurrogate) {
text += '-\\u' + toHex4Digits(this.lastTrailSurrogate);
}
return text;
}
}
class Writer {
constructor() {
/** @type {number} */
this.lastCodePoint = -1;
/** @type {NonSurrogateRange[]} */
this.nonSurrogateRanges = [];
/** @type {LeadSurrogateRange[]} */
this.surrogateRanges = [];
/** @type {NonSurrogateRange} */
this.nonSurrogateRange;
/** @type {LeadSurrogateRange} */
this.leadSurrogateRange;
/** @type {TrailSurrogateRange} */
this.trailSurrogateRange;
}
/** @param {number} codePoint */
push(codePoint) {
if (codePoint <= this.lastCodePoint)
throw new Error('Code points must be added in order.');
this.lastCodePoint = codePoint;
if (codePoint < MAX_UNICODE_NON_SURROGATE) {
if (
this.nonSurrogateRange &&
this.nonSurrogateRange.lastCodePoint === codePoint - 1
) {
this.nonSurrogateRange.lastCodePoint = codePoint;
return;
}
this.nonSurrogateRange = new NonSurrogateRange(codePoint);
this.nonSurrogateRanges.push(this.nonSurrogateRange);
} else {
const leadSurrogate = Math.floor((codePoint - 0x10000) / 0x400) + 0xd800;
const trailSurrogate = ((codePoint - 0x10000) % 0x400) + 0xdc00;
if (
!this.leadSurrogateRange ||
this.leadSurrogateRange.leadSurrogate !== leadSurrogate
) {
this.trailSurrogateRange = undefined;
this.leadSurrogateRange = new LeadSurrogateRange(leadSurrogate);
this.surrogateRanges.push(this.leadSurrogateRange);
}
if (
this.trailSurrogateRange &&
this.trailSurrogateRange.lastTrailSurrogate === trailSurrogate - 1
) {
this.trailSurrogateRange.lastTrailSurrogate = trailSurrogate;
return;
}
this.trailSurrogateRange = new TrailSurrogateRange(trailSurrogate);
this.leadSurrogateRange.ranges.push(this.trailSurrogateRange);
}
}
toString() {
let first = this.nonSurrogateRanges.join('');
let second = this.surrogateRanges.join('|');
return first && second
? `([${first}]|${second})`
: first
? `[${first}]`
: second
? `(${second})`
: '';
}
}
const MAX_UNICODE_NON_SURROGATE = 0xffff;
const MAX_UNICODE_CODEPOINT = 0x10ffff;
const isStart = c => /\p{ID_Start}/u.test(c);
const isContinue = c => /\p{ID_Continue}/u.test(c);
let idStartWriter = new Writer();
let idContinueWriter = new Writer();
for (let cp = 0; cp <= MAX_UNICODE_CODEPOINT; cp++) {
const ch = String.fromCodePoint(cp);
if (isStart(ch)) {
idStartWriter.push(cp);
}
if (isContinue(ch)) {
idContinueWriter.push(cp);
}
}
console.log(`/**
* Generated by scripts/generate-unicode-id-parts.js on node ${
process.version
} with unicode ${process.versions.unicode}
* based on http://www.unicode.org/reports/tr31/ and https://tc39.es/ecma262/#sec-names-and-keywords
* U_ID_START corresponds to the ID_Start property, and U_ID_CONTINUE corresponds to ID_Continue property.
*/`);
console.log('U_ID_START ' + idStartWriter.toString());
console.log('U_ID_CONTINUE ' + idContinueWriter.toString());
|