This commit is contained in:
2025-05-09 05:30:08 +02:00
parent 7bb10e7df4
commit 73367bad9e
5322 changed files with 1266973 additions and 313 deletions

View File

@@ -0,0 +1,480 @@
{
"bugs": {
"url": "https://github.com/nodejs/node-addon-api/issues"
},
"contributors": [
{
"name": "Abhishek Kumar Singh",
"url": "https://github.com/abhi11210646"
},
{
"name": "Alba Mendez",
"url": "https://github.com/jmendeth"
},
{
"name": "Alexander Floh",
"url": "https://github.com/alexanderfloh"
},
{
"name": "Ammar Faizi",
"url": "https://github.com/ammarfaizi2"
},
{
"name": "András Timár, Dr",
"url": "https://github.com/timarandras"
},
{
"name": "Andrew Petersen",
"url": "https://github.com/kirbysayshi"
},
{
"name": "Anisha Rohra",
"url": "https://github.com/anisha-rohra"
},
{
"name": "Anna Henningsen",
"url": "https://github.com/addaleax"
},
{
"name": "Arnaud Botella",
"url": "https://github.com/BotellaA"
},
{
"name": "Arunesh Chandra",
"url": "https://github.com/aruneshchandra"
},
{
"name": "Azlan Mukhtar",
"url": "https://github.com/azlan"
},
{
"name": "Ben Berman",
"url": "https://github.com/rivertam"
},
{
"name": "Benjamin Byholm",
"url": "https://github.com/kkoopa"
},
{
"name": "Bill Gallafent",
"url": "https://github.com/gallafent"
},
{
"name": "blagoev",
"url": "https://github.com/blagoev"
},
{
"name": "Bruce A. MacNaughton",
"url": "https://github.com/bmacnaughton"
},
{
"name": "Cory Mickelson",
"url": "https://github.com/corymickelson"
},
{
"name": "Daniel Bevenius",
"url": "https://github.com/danbev"
},
{
"name": "Dante Calderón",
"url": "https://github.com/dantehemerson"
},
{
"name": "Darshan Sen",
"url": "https://github.com/RaisinTen"
},
{
"name": "David Halls",
"url": "https://github.com/davedoesdev"
},
{
"name": "Deepak Rajamohan",
"url": "https://github.com/deepakrkris"
},
{
"name": "Dmitry Ashkadov",
"url": "https://github.com/dmitryash"
},
{
"name": "Dongjin Na",
"url": "https://github.com/nadongguri"
},
{
"name": "Doni Rubiagatra",
"url": "https://github.com/rubiagatra"
},
{
"name": "Eric Bickle",
"url": "https://github.com/ebickle"
},
{
"name": "extremeheat",
"url": "https://github.com/extremeheat"
},
{
"name": "Feng Yu",
"url": "https://github.com/F3n67u"
},
{
"name": "Ferdinand Holzer",
"url": "https://github.com/fholzer"
},
{
"name": "Gabriel Schulhof",
"url": "https://github.com/gabrielschulhof"
},
{
"name": "Guenter Sandner",
"url": "https://github.com/gms1"
},
{
"name": "Gus Caplan",
"url": "https://github.com/devsnek"
},
{
"name": "Helio Frota",
"url": "https://github.com/helio-frota"
},
{
"name": "Hitesh Kanwathirtha",
"url": "https://github.com/digitalinfinity"
},
{
"name": "ikokostya",
"url": "https://github.com/ikokostya"
},
{
"name": "Jack Xia",
"url": "https://github.com/JckXia"
},
{
"name": "Jake Barnes",
"url": "https://github.com/DuBistKomisch"
},
{
"name": "Jake Yoon",
"url": "https://github.com/yjaeseok"
},
{
"name": "Jason Ginchereau",
"url": "https://github.com/jasongin"
},
{
"name": "Jenny",
"url": "https://github.com/egg-bread"
},
{
"name": "Jeroen Janssen",
"url": "https://github.com/japj"
},
{
"name": "Jim Schlight",
"url": "https://github.com/jschlight"
},
{
"name": "Jinho Bang",
"url": "https://github.com/romandev"
},
{
"name": "José Expósito",
"url": "https://github.com/JoseExposito"
},
{
"name": "joshgarde",
"url": "https://github.com/joshgarde"
},
{
"name": "Julian Mesa",
"url": "https://github.com/julianmesa-gitkraken"
},
{
"name": "Kasumi Hanazuki",
"url": "https://github.com/hanazuki"
},
{
"name": "Kelvin",
"url": "https://github.com/kelvinhammond"
},
{
"name": "Kevin Eady",
"url": "https://github.com/KevinEady"
},
{
"name": "Kévin VOYER",
"url": "https://github.com/kecsou"
},
{
"name": "kidneysolo",
"url": "https://github.com/kidneysolo"
},
{
"name": "Koki Nishihara",
"url": "https://github.com/Nishikoh"
},
{
"name": "Konstantin Tarkus",
"url": "https://github.com/koistya"
},
{
"name": "Kyle Farnung",
"url": "https://github.com/kfarnung"
},
{
"name": "Kyle Kovacs",
"url": "https://github.com/nullromo"
},
{
"name": "legendecas",
"url": "https://github.com/legendecas"
},
{
"name": "LongYinan",
"url": "https://github.com/Brooooooklyn"
},
{
"name": "Lovell Fuller",
"url": "https://github.com/lovell"
},
{
"name": "Luciano Martorella",
"url": "https://github.com/lmartorella"
},
{
"name": "mastergberry",
"url": "https://github.com/mastergberry"
},
{
"name": "Mathias Küsel",
"url": "https://github.com/mathiask88"
},
{
"name": "Mathias Stearn",
"url": "https://github.com/RedBeard0531"
},
{
"name": "Matteo Collina",
"url": "https://github.com/mcollina"
},
{
"name": "Michael Dawson",
"url": "https://github.com/mhdawson"
},
{
"name": "Michael Price",
"url": "https://github.com/mikepricedev"
},
{
"name": "Michele Campus",
"url": "https://github.com/kYroL01"
},
{
"name": "Mikhail Cheshkov",
"url": "https://github.com/mcheshkov"
},
{
"name": "nempoBu4",
"url": "https://github.com/nempoBu4"
},
{
"name": "Nicola Del Gobbo",
"url": "https://github.com/NickNaso"
},
{
"name": "Nick Soggin",
"url": "https://github.com/iSkore"
},
{
"name": "Nikolai Vavilov",
"url": "https://github.com/seishun"
},
{
"name": "Nurbol Alpysbayev",
"url": "https://github.com/anurbol"
},
{
"name": "pacop",
"url": "https://github.com/pacop"
},
{
"name": "Peter Šándor",
"url": "https://github.com/petersandor"
},
{
"name": "Philipp Renoth",
"url": "https://github.com/DaAitch"
},
{
"name": "rgerd",
"url": "https://github.com/rgerd"
},
{
"name": "Richard Lau",
"url": "https://github.com/richardlau"
},
{
"name": "Rolf Timmermans",
"url": "https://github.com/rolftimmermans"
},
{
"name": "Ross Weir",
"url": "https://github.com/ross-weir"
},
{
"name": "Ryuichi Okumura",
"url": "https://github.com/okuryu"
},
{
"name": "Saint Gabriel",
"url": "https://github.com/chineduG"
},
{
"name": "Sampson Gao",
"url": "https://github.com/sampsongao"
},
{
"name": "Sam Roberts",
"url": "https://github.com/sam-github"
},
{
"name": "strager",
"url": "https://github.com/strager"
},
{
"name": "Taylor Woll",
"url": "https://github.com/boingoing"
},
{
"name": "Thomas Gentilhomme",
"url": "https://github.com/fraxken"
},
{
"name": "Tim Rach",
"url": "https://github.com/timrach"
},
{
"name": "Tobias Nießen",
"url": "https://github.com/tniessen"
},
{
"name": "todoroff",
"url": "https://github.com/todoroff"
},
{
"name": "Toyo Li",
"url": "https://github.com/toyobayashi"
},
{
"name": "Tux3",
"url": "https://github.com/tux3"
},
{
"name": "Vlad Velmisov",
"url": "https://github.com/Velmisov"
},
{
"name": "Vladimir Morozov",
"url": "https://github.com/vmoroz"
},
{
"name": "WenheLI",
"url": "https://github.com/WenheLI"
},
{
"name": "Xuguang Mei",
"url": "https://github.com/meixg"
},
{
"name": "Yohei Kishimoto",
"url": "https://github.com/morokosi"
},
{
"name": "Yulong Wang",
"url": "https://github.com/fs-eire"
},
{
"name": "Ziqiu Zhao",
"url": "https://github.com/ZzqiZQute"
},
{
"name": "Feng Yu",
"url": "https://github.com/F3n67u"
},
{
"name": "wanlu wang",
"url": "https://github.com/wanlu"
},
{
"name": "Caleb Hearon",
"url": "https://github.com/chearon"
},
{
"name": "Marx",
"url": "https://github.com/MarxJiao"
},
{
"name": "Ömer AKGÜL",
"url": "https://github.com/tuhalf"
}
],
"description": "Node.js API (Node-API)",
"devDependencies": {
"benchmark": "^2.1.4",
"bindings": "^1.5.0",
"clang-format": "^1.4.0",
"eslint": "^7.32.0",
"eslint-config-semistandard": "^16.0.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"fs-extra": "^11.1.1",
"path": "^0.12.7",
"pre-commit": "^1.2.2",
"safe-buffer": "^5.1.1"
},
"directories": {},
"gypfile": false,
"homepage": "https://github.com/nodejs/node-addon-api",
"keywords": [
"n-api",
"napi",
"addon",
"native",
"bindings",
"c",
"c++",
"nan",
"node-addon-api"
],
"license": "MIT",
"main": "index.js",
"name": "node-addon-api",
"readme": "README.md",
"repository": {
"type": "git",
"url": "git://github.com/nodejs/node-addon-api.git"
},
"files": [
"*.{c,h,gyp,gypi}",
"package-support.json",
"tools/"
],
"scripts": {
"prebenchmark": "node-gyp rebuild -C benchmark",
"benchmark": "node benchmark",
"pretest": "node-gyp rebuild -C test",
"test": "node test",
"test:debug": "node-gyp rebuild -C test --debug && NODE_API_BUILD_CONFIG=Debug node ./test/index.js",
"predev": "node-gyp rebuild -C test --debug",
"dev": "node test",
"predev:incremental": "node-gyp configure build -C test --debug",
"dev:incremental": "node test",
"doc": "doxygen doc/Doxyfile",
"lint": "node tools/eslint-format && node tools/clang-format",
"lint:fix": "node tools/clang-format --fix && node tools/eslint-format --fix"
},
"pre-commit": "lint",
"version": "7.1.1",
"support": true
}

View File

@@ -0,0 +1 @@
module.exports={A:{A:{"1":"F A B","2":"mC","8":"K","132":"D E"},B:{"1":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC qC rC","2":"nC LC"},D:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC"},E:{"1":"J PB K D E F A B C L M G SC tC uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","2":"sC"},F:{"1":"0 1 2 3 4 5 6 7 8 B C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 4C 5C 6C 7C FC kC 8C GC","2":"F"},G:{"1":"E SC 9C lC AD BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC"},H:{"1":"WD"},I:{"1":"LC J I XD YD ZD aD lC bD cD"},J:{"1":"D A"},K:{"1":"A B C H FC kC GC"},L:{"1":"I"},M:{"1":"EC"},N:{"1":"A B"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"qD rD"}},B:2,C:"CSS3 selectors",D:true};

View File

@@ -0,0 +1,56 @@
import type { PDFPageProxy } from 'pdfjs-dist';
import type { PageCallback } from './types.js';
/**
* Checks if we're running in a browser environment.
*/
export declare const isBrowser: boolean;
/**
* Checks whether we're running from a local file system.
*/
export declare const isLocalFileSystem: boolean;
/**
* Checks whether a variable is defined.
*
* @param {*} variable Variable to check
*/
export declare function isDefined<T>(variable: T | undefined): variable is T;
/**
* Checks whether a variable is defined and not null.
*
* @param {*} variable Variable to check
*/
export declare function isProvided<T>(variable: T | null | undefined): variable is T;
/**
* Checks whether a variable provided is a string.
*
* @param {*} variable Variable to check
*/
export declare function isString(variable: unknown): variable is string;
/**
* Checks whether a variable provided is an ArrayBuffer.
*
* @param {*} variable Variable to check
*/
export declare function isArrayBuffer(variable: unknown): variable is ArrayBuffer;
/**
* Checks whether a variable provided is a Blob.
*
* @param {*} variable Variable to check
*/
export declare function isBlob(variable: unknown): variable is Blob;
/**
* Checks whether a variable provided is a data URI.
*
* @param {*} variable String to check
*/
export declare function isDataURI(variable: unknown): variable is `data:${string}`;
export declare function dataURItoByteString(dataURI: unknown): string;
export declare function getDevicePixelRatio(): number;
export declare function displayCORSWarning(): void;
export declare function displayWorkerWarning(): void;
export declare function cancelRunningTask(runningTask?: {
cancel?: () => void;
} | null): void;
export declare function makePageCallback(page: PDFPageProxy, scale: number): PageCallback;
export declare function isCancelException(error: Error): boolean;
export declare function loadFromFile(file: Blob): Promise<ArrayBuffer>;

View File

@@ -0,0 +1,11 @@
"use strict";
module.exports = function (it) {
const { path, message } = it;
return `
Failed to read JSON file at ${path}:
${message}
`.trimStart();
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["_index","require","_index2","_default","exports","default","toStatement","node","ignore","isStatement","mustHaveId","newType","isClass","isFunction","isAssignmentExpression","expressionStatement","id","Error","type"],"sources":["../../src/converters/toStatement.ts"],"sourcesContent":["import {\n isStatement,\n isFunction,\n isClass,\n isAssignmentExpression,\n} from \"../validators/generated/index.ts\";\nimport { expressionStatement } from \"../builders/generated/index.ts\";\nimport type * as t from \"../index.ts\";\n\nexport default toStatement as {\n (node: t.AssignmentExpression, ignore?: boolean): t.ExpressionStatement;\n\n <T extends t.Statement>(node: T, ignore: false): T;\n <T extends t.Statement>(node: T, ignore?: boolean): T | false;\n\n (node: t.Class, ignore: false): t.ClassDeclaration;\n (node: t.Class, ignore?: boolean): t.ClassDeclaration | false;\n\n (node: t.Function, ignore: false): t.FunctionDeclaration;\n (node: t.Function, ignore?: boolean): t.FunctionDeclaration | false;\n\n (node: t.Node, ignore: false): t.Statement;\n (node: t.Node, ignore?: boolean): t.Statement | false;\n};\n\nfunction toStatement(node: t.Node, ignore?: boolean): t.Statement | false {\n if (isStatement(node)) {\n return node;\n }\n\n let mustHaveId = false;\n let newType;\n\n if (isClass(node)) {\n mustHaveId = true;\n newType = \"ClassDeclaration\" as const;\n } else if (isFunction(node)) {\n mustHaveId = true;\n newType = \"FunctionDeclaration\" as const;\n } else if (isAssignmentExpression(node)) {\n return expressionStatement(node);\n }\n\n // @ts-expect-error todo(flow->ts): node.id might be missing\n if (mustHaveId && !node.id) {\n newType = false;\n }\n\n if (!newType) {\n if (ignore) {\n return false;\n } else {\n throw new Error(`cannot turn ${node.type} to a statement`);\n }\n }\n\n // @ts-expect-error manipulating node.type\n node.type = newType;\n\n // @ts-expect-error todo(flow->ts) refactor to avoid type unsafe mutations like reassigning node type above\n return node;\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAMA,IAAAC,OAAA,GAAAD,OAAA;AAAqE,IAAAE,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAGtDC,WAAW;AAgB1B,SAASA,WAAWA,CAACC,IAAY,EAAEC,MAAgB,EAAuB;EACxE,IAAI,IAAAC,kBAAW,EAACF,IAAI,CAAC,EAAE;IACrB,OAAOA,IAAI;EACb;EAEA,IAAIG,UAAU,GAAG,KAAK;EACtB,IAAIC,OAAO;EAEX,IAAI,IAAAC,cAAO,EAACL,IAAI,CAAC,EAAE;IACjBG,UAAU,GAAG,IAAI;IACjBC,OAAO,GAAG,kBAA2B;EACvC,CAAC,MAAM,IAAI,IAAAE,iBAAU,EAACN,IAAI,CAAC,EAAE;IAC3BG,UAAU,GAAG,IAAI;IACjBC,OAAO,GAAG,qBAA8B;EAC1C,CAAC,MAAM,IAAI,IAAAG,6BAAsB,EAACP,IAAI,CAAC,EAAE;IACvC,OAAO,IAAAQ,2BAAmB,EAACR,IAAI,CAAC;EAClC;EAGA,IAAIG,UAAU,IAAI,CAACH,IAAI,CAACS,EAAE,EAAE;IAC1BL,OAAO,GAAG,KAAK;EACjB;EAEA,IAAI,CAACA,OAAO,EAAE;IACZ,IAAIH,MAAM,EAAE;MACV,OAAO,KAAK;IACd,CAAC,MAAM;MACL,MAAM,IAAIS,KAAK,CAAC,eAAeV,IAAI,CAACW,IAAI,iBAAiB,CAAC;IAC5D;EACF;EAGAX,IAAI,CAACW,IAAI,GAAGP,OAAO;EAGnB,OAAOJ,IAAI;AACb","ignoreList":[]}

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isIterableIterator = isIterableIterator;
exports.mergeOptions = mergeOptions;
function mergeOptions(target, source) {
for (const k of Object.keys(source)) {
if ((k === "parserOpts" || k === "generatorOpts" || k === "assumptions") && source[k]) {
const parserOpts = source[k];
const targetObj = target[k] || (target[k] = {});
mergeDefaultFields(targetObj, parserOpts);
} else {
const val = source[k];
if (val !== undefined) target[k] = val;
}
}
}
function mergeDefaultFields(target, source) {
for (const k of Object.keys(source)) {
const val = source[k];
if (val !== undefined) target[k] = val;
}
}
function isIterableIterator(value) {
return !!value && typeof value.next === "function" && typeof value[Symbol.iterator] === "function";
}
0 && 0;
//# sourceMappingURL=util.js.map

View File

@@ -0,0 +1,5 @@
{
"name": "beep-boop",
"version": "1.2.3",
"repository" : "git@github.com:substack/beep-boop.git"
}

View File

@@ -0,0 +1,98 @@
var path = require('path');
var fs = require('fs');
var _0777 = parseInt('0777', 8);
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
function mkdirP (p, opts, f, made) {
if (typeof opts === 'function') {
f = opts;
opts = {};
}
else if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
var cb = f || function () {};
p = path.resolve(p);
xfs.mkdir(p, mode, function (er) {
if (!er) {
made = made || p;
return cb(null, made);
}
switch (er.code) {
case 'ENOENT':
mkdirP(path.dirname(p), opts, function (er, made) {
if (er) cb(er, made);
else mkdirP(p, opts, cb, made);
});
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
xfs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
if (er2 || !stat.isDirectory()) cb(er, made)
else cb(null, made);
});
break;
}
});
}
mkdirP.sync = function sync (p, opts, made) {
if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
p = path.resolve(p);
try {
xfs.mkdirSync(p, mode);
made = made || p;
}
catch (err0) {
switch (err0.code) {
case 'ENOENT' :
made = sync(path.dirname(p), opts, made);
sync(p, opts, made);
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
var stat;
try {
stat = xfs.statSync(p);
}
catch (err1) {
throw err0;
}
if (!stat.isDirectory()) throw err0;
break;
}
}
return made;
};

View File

@@ -0,0 +1,39 @@
// @flow
export interface Targets {
android?: number;
chrome?: number;
edge?: number;
firefox?: number;
ie?: number;
ios_saf?: number;
opera?: number;
safari?: number;
samsung?: number;
}
declare export var Features: {|
Nesting: 1,
NotSelectorList: 2,
DirSelector: 4,
LangSelectorList: 8,
IsSelector: 16,
TextDecorationThicknessPercent: 32,
MediaIntervalSyntax: 64,
MediaRangeSyntax: 128,
CustomMediaQueries: 256,
ClampFunction: 512,
ColorFunction: 1024,
OklabColors: 2048,
LabColors: 4096,
P3Colors: 8192,
HexAlphaColors: 16384,
SpaceSeparatedColorNotation: 32768,
FontFamilySystemUi: 65536,
DoublePositionGradients: 131072,
VendorPrefixes: 262144,
LogicalProperties: 524288,
LightDark: 1048576,
Selectors: 31,
MediaQueries: 448,
Colors: 1113088,
|};

View File

@@ -0,0 +1,541 @@
import AtRule = require('./at-rule.js')
import { AtRuleProps } from './at-rule.js'
import Comment, { CommentProps } from './comment.js'
import Container, { NewChild } from './container.js'
import CssSyntaxError from './css-syntax-error.js'
import Declaration, { DeclarationProps } from './declaration.js'
import Document from './document.js'
import Input from './input.js'
import { Stringifier, Syntax } from './postcss.js'
import Result from './result.js'
import Root from './root.js'
import Rule, { RuleProps } from './rule.js'
import Warning, { WarningOptions } from './warning.js'
declare namespace Node {
export type ChildNode = AtRule.default | Comment | Declaration | Rule
export type AnyNode =
| AtRule.default
| Comment
| Declaration
| Document
| Root
| Rule
export type ChildProps =
| AtRuleProps
| CommentProps
| DeclarationProps
| RuleProps
export interface Position {
/**
* Source line in file. In contrast to `offset` it starts from 1.
*/
column: number
/**
* Source column in file.
*/
line: number
/**
* Source offset in file. It starts from 0.
*/
offset: number
}
export interface Range {
/**
* End position, exclusive.
*/
end: Position
/**
* Start position, inclusive.
*/
start: Position
}
/**
* Source represents an interface for the {@link Node.source} property.
*/
export interface Source {
/**
* The inclusive ending position for the source
* code of a node.
*/
end?: Position
/**
* The source file from where a node has originated.
*/
input: Input
/**
* The inclusive starting position for the source
* code of a node.
*/
start?: Position
}
/**
* Interface represents an interface for an object received
* as parameter by Node class constructor.
*/
export interface NodeProps {
source?: Source
}
export interface NodeErrorOptions {
/**
* An ending index inside a node's string that should be highlighted as
* source of error.
*/
endIndex?: number
/**
* An index inside a node's string that should be highlighted as source
* of error.
*/
index?: number
/**
* Plugin name that created this error. PostCSS will set it automatically.
*/
plugin?: string
/**
* A word inside a node's string, that should be highlighted as source
* of error.
*/
word?: string
}
// eslint-disable-next-line @typescript-eslint/no-shadow
class Node extends Node_ {}
export { Node as default }
}
/**
* It represents an abstract class that handles common
* methods for other CSS abstract syntax tree nodes.
*
* Any node that represents CSS selector or value should
* not extend the `Node` class.
*/
declare abstract class Node_ {
/**
* It represents parent of the current node.
*
* ```js
* root.nodes[0].parent === root //=> true
* ```
*/
parent: Container | Document | undefined
/**
* It represents unnecessary whitespace and characters present
* in the css source code.
*
* Information to generate byte-to-byte equal node string as it was
* in the origin input.
*
* The properties of the raws object are decided by parser,
* the default parser uses the following properties:
*
* * `before`: the space symbols before the node. It also stores `*`
* and `_` symbols before the declaration (IE hack).
* * `after`: the space symbols after the last child of the node
* to the end of the node.
* * `between`: the symbols between the property and value
* for declarations, selector and `{` for rules, or last parameter
* and `{` for at-rules.
* * `semicolon`: contains true if the last child has
* an (optional) semicolon.
* * `afterName`: the space between the at-rule name and its parameters.
* * `left`: the space symbols between `/*` and the comments text.
* * `right`: the space symbols between the comments text
* and <code>*&#47;</code>.
* - `important`: the content of the important statement,
* if it is not just `!important`.
*
* PostCSS filters out the comments inside selectors, declaration values
* and at-rule parameters but it stores the origin content in raws.
*
* ```js
* const root = postcss.parse('a {\n color:black\n}')
* root.first.first.raws //=> { before: '\n ', between: ':' }
* ```
*/
raws: any
/**
* It represents information related to origin of a node and is required
* for generating source maps.
*
* The nodes that are created manually using the public APIs
* provided by PostCSS will have `source` undefined and
* will be absent in the source map.
*
* For this reason, the plugin developer should consider
* duplicating nodes as the duplicate node will have the
* same source as the original node by default or assign
* source to a node created manually.
*
* ```js
* decl.source.input.from //=> '/home/ai/source.css'
* decl.source.start //=> { line: 10, column: 2 }
* decl.source.end //=> { line: 10, column: 12 }
* ```
*
* ```js
* // Incorrect method, source not specified!
* const prefixed = postcss.decl({
* prop: '-moz-' + decl.prop,
* value: decl.value
* })
*
* // Correct method, source is inherited when duplicating.
* const prefixed = decl.clone({
* prop: '-moz-' + decl.prop
* })
* ```
*
* ```js
* if (atrule.name === 'add-link') {
* const rule = postcss.rule({
* selector: 'a',
* source: atrule.source
* })
*
* atrule.parent.insertBefore(atrule, rule)
* }
* ```
*/
source?: Node.Source
/**
* It represents type of a node in
* an abstract syntax tree.
*
* A type of node helps in identification of a node
* and perform operation based on it's type.
*
* ```js
* const declaration = new Declaration({
* prop: 'color',
* value: 'black'
* })
*
* declaration.type //=> 'decl'
* ```
*/
type: string
constructor(defaults?: object)
/**
* Insert new node after current node to current nodes parent.
*
* Just alias for `node.parent.insertAfter(node, add)`.
*
* ```js
* decl.after('color: black')
* ```
*
* @param newNode New node.
* @return This node for methods chain.
*/
after(
newNode: Node | Node.ChildProps | readonly Node[] | string | undefined
): this
/**
* It assigns properties to an existing node instance.
*
* ```js
* decl.assign({ prop: 'word-wrap', value: 'break-word' })
* ```
*
* @param overrides New properties to override the node.
*
* @return `this` for method chaining.
*/
assign(overrides: object): this
/**
* Insert new node before current node to current nodes parent.
*
* Just alias for `node.parent.insertBefore(node, add)`.
*
* ```js
* decl.before('content: ""')
* ```
*
* @param newNode New node.
* @return This node for methods chain.
*/
before(
newNode: Node | Node.ChildProps | readonly Node[] | string | undefined
): this
/**
* Clear the code style properties for the node and its children.
*
* ```js
* node.raws.before //=> ' '
* node.cleanRaws()
* node.raws.before //=> undefined
* ```
*
* @param keepBetween Keep the `raws.between` symbols.
*/
cleanRaws(keepBetween?: boolean): void
/**
* It creates clone of an existing node, which includes all the properties
* and their values, that includes `raws` but not `type`.
*
* ```js
* decl.raws.before //=> "\n "
* const cloned = decl.clone({ prop: '-moz-' + decl.prop })
* cloned.raws.before //=> "\n "
* cloned.toString() //=> -moz-transform: scale(0)
* ```
*
* @param overrides New properties to override in the clone.
*
* @return Duplicate of the node instance.
*/
clone(overrides?: object): this
/**
* Shortcut to clone the node and insert the resulting cloned node
* after the current node.
*
* @param overrides New properties to override in the clone.
* @return New node.
*/
cloneAfter(overrides?: object): this
/**
* Shortcut to clone the node and insert the resulting cloned node
* before the current node.
*
* ```js
* decl.cloneBefore({ prop: '-moz-' + decl.prop })
* ```
*
* @param overrides Mew properties to override in the clone.
*
* @return New node
*/
cloneBefore(overrides?: object): this
/**
* It creates an instance of the class `CssSyntaxError` and parameters passed
* to this method are assigned to the error instance.
*
* The error instance will have description for the
* error, original position of the node in the
* source, showing line and column number.
*
* If any previous map is present, it would be used
* to get original position of the source.
*
* The Previous Map here is referred to the source map
* generated by previous compilation, example: Less,
* Stylus and Sass.
*
* This method returns the error instance instead of
* throwing it.
*
* ```js
* if (!variables[name]) {
* throw decl.error(`Unknown variable ${name}`, { word: name })
* // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black
* // color: $black
* // a
* // ^
* // background: white
* }
* ```
*
* @param message Description for the error instance.
* @param options Options for the error instance.
*
* @return Error instance is returned.
*/
error(message: string, options?: Node.NodeErrorOptions): CssSyntaxError
/**
* Returns the next child of the nodes parent.
* Returns `undefined` if the current node is the last child.
*
* ```js
* if (comment.text === 'delete next') {
* const next = comment.next()
* if (next) {
* next.remove()
* }
* }
* ```
*
* @return Next node.
*/
next(): Node.ChildNode | undefined
/**
* Get the position for a word or an index inside the node.
*
* @param opts Options.
* @return Position.
*/
positionBy(opts?: Pick<WarningOptions, 'index' | 'word'>): Node.Position
/**
* Convert string index to line/column.
*
* @param index The symbol number in the nodes string.
* @return Symbol position in file.
*/
positionInside(index: number): Node.Position
/**
* Returns the previous child of the nodes parent.
* Returns `undefined` if the current node is the first child.
*
* ```js
* const annotation = decl.prev()
* if (annotation.type === 'comment') {
* readAnnotation(annotation.text)
* }
* ```
*
* @return Previous node.
*/
prev(): Node.ChildNode | undefined
/**
* Get the range for a word or start and end index inside the node.
* The start index is inclusive; the end index is exclusive.
*
* @param opts Options.
* @return Range.
*/
rangeBy(
opts?: Pick<WarningOptions, 'endIndex' | 'index' | 'word'>
): Node.Range
/**
* Returns a `raws` value. If the node is missing
* the code style property (because the node was manually built or cloned),
* PostCSS will try to autodetect the code style property by looking
* at other nodes in the tree.
*
* ```js
* const root = postcss.parse('a { background: white }')
* root.nodes[0].append({ prop: 'color', value: 'black' })
* root.nodes[0].nodes[1].raws.before //=> undefined
* root.nodes[0].nodes[1].raw('before') //=> ' '
* ```
*
* @param prop Name of code style property.
* @param defaultType Name of default value, it can be missed
* if the value is the same as prop.
* @return {string} Code style value.
*/
raw(prop: string, defaultType?: string): string
/**
* It removes the node from its parent and deletes its parent property.
*
* ```js
* if (decl.prop.match(/^-webkit-/)) {
* decl.remove()
* }
* ```
*
* @return `this` for method chaining.
*/
remove(): this
/**
* Inserts node(s) before the current node and removes the current node.
*
* ```js
* AtRule: {
* mixin: atrule => {
* atrule.replaceWith(mixinRules[atrule.params])
* }
* }
* ```
*
* @param nodes Mode(s) to replace current one.
* @return Current node to methods chain.
*/
replaceWith(...nodes: NewChild[]): this
/**
* Finds the Root instance of the nodes tree.
*
* ```js
* root.nodes[0].nodes[0].root() === root
* ```
*
* @return Root parent.
*/
root(): Root
/**
* Fix circular links on `JSON.stringify()`.
*
* @return Cleaned object.
*/
toJSON(): object
/**
* It compiles the node to browser readable cascading style sheets string
* depending on it's type.
*
* ```js
* new Rule({ selector: 'a' }).toString() //=> "a {}"
* ```
*
* @param stringifier A syntax to use in string generation.
* @return CSS string of this node.
*/
toString(stringifier?: Stringifier | Syntax): string
/**
* It is a wrapper for {@link Result#warn}, providing convenient
* way of generating warnings.
*
* ```js
* Declaration: {
* bad: (decl, { result }) => {
* decl.warn(result, 'Deprecated property: bad')
* }
* }
* ```
*
* @param result The `Result` instance that will receive the warning.
* @param message Description for the warning.
* @param options Options for the warning.
*
* @return `Warning` instance is returned
*/
warn(result: Result, message: string, options?: WarningOptions): Warning
/**
* If this node isn't already dirty, marks it and its ancestors as such. This
* indicates to the LazyResult processor that the {@link Root} has been
* modified by the current plugin and may need to be processed again by other
* plugins.
*/
protected markDirty(): void
}
declare class Node extends Node_ {}
export = Node

View File

@@ -0,0 +1,15 @@
type Promisable<T> = T | Promise<T>;
declare namespace escalade {
export type Callback = (
directory: string,
files: string[],
) => Promisable<string | false | void>;
}
declare function escalade(
directory: string,
callback: escalade.Callback,
): Promise<string | void>;
export = escalade;

View File

@@ -0,0 +1,48 @@
#include "SvgBackend.h"
#include <cairo-svg.h>
#include <napi.h>
#include "../Canvas.h"
#include "../closure.h"
#include "../InstanceData.h"
#include <cassert>
using namespace Napi;
SvgBackend::SvgBackend(Napi::CallbackInfo& info) : Napi::ObjectWrap<SvgBackend>(info), Backend("svg", info) {
SvgBackend::createSurface();
}
SvgBackend::~SvgBackend() {
cairo_surface_finish(surface);
if (_closure) {
delete _closure;
_closure = nullptr;
}
destroySurface();
}
cairo_surface_t* SvgBackend::createSurface() {
assert(!_closure);
_closure = new PdfSvgClosure(canvas);
surface = cairo_svg_surface_create_for_stream(PdfSvgClosure::writeVec, _closure, width, height);
return surface;
}
cairo_surface_t* SvgBackend::recreateSurface() {
cairo_surface_finish(surface);
delete _closure;
_closure = nullptr;
cairo_surface_destroy(surface);
return createSurface();
}
void
SvgBackend::Initialize(Napi::Object target) {
Napi::Env env = target.Env();
Napi::Function ctor = DefineClass(env, "SvgBackend", {});
InstanceData* data = env.GetInstanceData<InstanceData>();
data->SvgBackendCtor = Napi::Persistent(ctor);
}

View File

@@ -0,0 +1,708 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import estraverse from "estraverse";
import esrecurse from "esrecurse";
import Reference from "./reference.js";
import Variable from "./variable.js";
import PatternVisitor from "./pattern-visitor.js";
import { Definition, ParameterDefinition } from "./definition.js";
import { assert } from "./assert.js";
const { Syntax } = estraverse;
/**
* Traverse identifier in pattern
* @param {Object} options options
* @param {pattern} rootPattern root pattern
* @param {Refencer} referencer referencer
* @param {callback} callback callback
* @returns {void}
*/
function traverseIdentifierInPattern(options, rootPattern, referencer, callback) {
// Call the callback at left hand identifier nodes, and Collect right hand nodes.
const visitor = new PatternVisitor(options, rootPattern, callback);
visitor.visit(rootPattern);
// Process the right hand nodes recursively.
if (referencer !== null && referencer !== void 0) {
visitor.rightHandNodes.forEach(referencer.visit, referencer);
}
}
// Importing ImportDeclaration.
// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
// https://github.com/estree/estree/blob/master/es6.md#importdeclaration
// FIXME: Now, we don't create module environment, because the context is
// implementation dependent.
/**
* Visitor for import specifiers.
*/
class Importer extends esrecurse.Visitor {
constructor(declaration, referencer) {
super(null, referencer.options);
this.declaration = declaration;
this.referencer = referencer;
}
visitImport(id, specifier) {
this.referencer.visitPattern(id, pattern => {
this.referencer.currentScope().__define(pattern,
new Definition(
Variable.ImportBinding,
pattern,
specifier,
this.declaration,
null,
null
));
});
}
ImportNamespaceSpecifier(node) {
const local = (node.local || node.id);
if (local) {
this.visitImport(local, node);
}
}
ImportDefaultSpecifier(node) {
const local = (node.local || node.id);
this.visitImport(local, node);
}
ImportSpecifier(node) {
const local = (node.local || node.id);
if (node.name) {
this.visitImport(node.name, node);
} else {
this.visitImport(local, node);
}
}
}
/**
* Referencing variables and creating bindings.
*/
class Referencer extends esrecurse.Visitor {
constructor(options, scopeManager) {
super(null, options);
this.options = options;
this.scopeManager = scopeManager;
this.parent = null;
this.isInnerMethodDefinition = false;
}
currentScope() {
return this.scopeManager.__currentScope;
}
close(node) {
while (this.currentScope() && node === this.currentScope().block) {
this.scopeManager.__currentScope = this.currentScope().__close(this.scopeManager);
}
}
pushInnerMethodDefinition(isInnerMethodDefinition) {
const previous = this.isInnerMethodDefinition;
this.isInnerMethodDefinition = isInnerMethodDefinition;
return previous;
}
popInnerMethodDefinition(isInnerMethodDefinition) {
this.isInnerMethodDefinition = isInnerMethodDefinition;
}
referencingDefaultValue(pattern, assignments, maybeImplicitGlobal, init) {
const scope = this.currentScope();
assignments.forEach(assignment => {
scope.__referencing(
pattern,
Reference.WRITE,
assignment.right,
maybeImplicitGlobal,
pattern !== assignment.left,
init
);
});
}
visitPattern(node, options, callback) {
let visitPatternOptions = options;
let visitPatternCallback = callback;
if (typeof options === "function") {
visitPatternCallback = options;
visitPatternOptions = { processRightHandNodes: false };
}
traverseIdentifierInPattern(
this.options,
node,
visitPatternOptions.processRightHandNodes ? this : null,
visitPatternCallback
);
}
visitFunction(node) {
let i, iz;
// FunctionDeclaration name is defined in upper scope
// NOTE: Not referring variableScope. It is intended.
// Since
// in ES5, FunctionDeclaration should be in FunctionBody.
// in ES6, FunctionDeclaration should be block scoped.
if (node.type === Syntax.FunctionDeclaration) {
// id is defined in upper scope
this.currentScope().__define(node.id,
new Definition(
Variable.FunctionName,
node.id,
node,
null,
null,
null
));
}
// FunctionExpression with name creates its special scope;
// FunctionExpressionNameScope.
if (node.type === Syntax.FunctionExpression && node.id) {
this.scopeManager.__nestFunctionExpressionNameScope(node);
}
// Consider this function is in the MethodDefinition.
this.scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
const that = this;
/**
* Visit pattern callback
* @param {pattern} pattern pattern
* @param {Object} info info
* @returns {void}
*/
function visitPatternCallback(pattern, info) {
that.currentScope().__define(pattern,
new ParameterDefinition(
pattern,
node,
i,
info.rest
));
that.referencingDefaultValue(pattern, info.assignments, null, true);
}
// Process parameter declarations.
for (i = 0, iz = node.params.length; i < iz; ++i) {
this.visitPattern(node.params[i], { processRightHandNodes: true }, visitPatternCallback);
}
// if there's a rest argument, add that
if (node.rest) {
this.visitPattern({
type: "RestElement",
argument: node.rest
}, pattern => {
this.currentScope().__define(pattern,
new ParameterDefinition(
pattern,
node,
node.params.length,
true
));
});
}
// In TypeScript there are a number of function-like constructs which have no body,
// so check it exists before traversing
if (node.body) {
// Skip BlockStatement to prevent creating BlockStatement scope.
if (node.body.type === Syntax.BlockStatement) {
this.visitChildren(node.body);
} else {
this.visit(node.body);
}
}
this.close(node);
}
visitClass(node) {
if (node.type === Syntax.ClassDeclaration) {
this.currentScope().__define(node.id,
new Definition(
Variable.ClassName,
node.id,
node,
null,
null,
null
));
}
this.scopeManager.__nestClassScope(node);
if (node.id) {
this.currentScope().__define(node.id,
new Definition(
Variable.ClassName,
node.id,
node
));
}
this.visit(node.superClass);
this.visit(node.body);
this.close(node);
}
visitProperty(node) {
let previous;
if (node.computed) {
this.visit(node.key);
}
const isMethodDefinition = node.type === Syntax.MethodDefinition;
if (isMethodDefinition) {
previous = this.pushInnerMethodDefinition(true);
}
this.visit(node.value);
if (isMethodDefinition) {
this.popInnerMethodDefinition(previous);
}
}
visitForIn(node) {
if (node.left.type === Syntax.VariableDeclaration && node.left.kind !== "var") {
this.scopeManager.__nestForScope(node);
}
if (node.left.type === Syntax.VariableDeclaration) {
this.visit(node.left);
this.visitPattern(node.left.declarations[0].id, pattern => {
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true, true);
});
} else {
this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
let maybeImplicitGlobal = null;
if (!this.currentScope().isStrict) {
maybeImplicitGlobal = {
pattern,
node
};
}
this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, true, false);
});
}
this.visit(node.right);
this.visit(node.body);
this.close(node);
}
visitVariableDeclaration(variableTargetScope, type, node, index) {
const decl = node.declarations[index];
const init = decl.init;
this.visitPattern(decl.id, { processRightHandNodes: true }, (pattern, info) => {
variableTargetScope.__define(
pattern,
new Definition(
type,
pattern,
decl,
node,
index,
node.kind
)
);
this.referencingDefaultValue(pattern, info.assignments, null, true);
if (init) {
this.currentScope().__referencing(pattern, Reference.WRITE, init, null, !info.topLevel, true);
}
});
}
AssignmentExpression(node) {
if (PatternVisitor.isPattern(node.left)) {
if (node.operator === "=") {
this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
let maybeImplicitGlobal = null;
if (!this.currentScope().isStrict) {
maybeImplicitGlobal = {
pattern,
node
};
}
this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, !info.topLevel, false);
});
} else {
this.currentScope().__referencing(node.left, Reference.RW, node.right);
}
} else {
this.visit(node.left);
}
this.visit(node.right);
}
CatchClause(node) {
this.scopeManager.__nestCatchScope(node);
this.visitPattern(node.param, { processRightHandNodes: true }, (pattern, info) => {
this.currentScope().__define(pattern,
new Definition(
Variable.CatchClause,
pattern,
node,
null,
null,
null
));
this.referencingDefaultValue(pattern, info.assignments, null, true);
});
this.visit(node.body);
this.close(node);
}
Program(node) {
this.scopeManager.__nestGlobalScope(node);
if (this.scopeManager.isGlobalReturn()) {
// Force strictness of GlobalScope to false when using node.js scope.
this.currentScope().isStrict = false;
this.scopeManager.__nestFunctionScope(node, false);
}
if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
this.scopeManager.__nestModuleScope(node);
}
if (this.scopeManager.isStrictModeSupported() && this.scopeManager.isImpliedStrict()) {
this.currentScope().isStrict = true;
}
this.visitChildren(node);
this.close(node);
}
Identifier(node) {
this.currentScope().__referencing(node);
}
// eslint-disable-next-line class-methods-use-this -- Desired as instance method
PrivateIdentifier() {
// Do nothing.
}
UpdateExpression(node) {
if (PatternVisitor.isPattern(node.argument)) {
this.currentScope().__referencing(node.argument, Reference.RW, null);
} else {
this.visitChildren(node);
}
}
MemberExpression(node) {
this.visit(node.object);
if (node.computed) {
this.visit(node.property);
}
}
Property(node) {
this.visitProperty(node);
}
PropertyDefinition(node) {
const { computed, key, value } = node;
if (computed) {
this.visit(key);
}
if (value) {
this.scopeManager.__nestClassFieldInitializerScope(value);
this.visit(value);
this.close(value);
}
}
StaticBlock(node) {
this.scopeManager.__nestClassStaticBlockScope(node);
this.visitChildren(node);
this.close(node);
}
MethodDefinition(node) {
this.visitProperty(node);
}
BreakStatement() {} // eslint-disable-line class-methods-use-this -- Desired as instance method
ContinueStatement() {} // eslint-disable-line class-methods-use-this -- Desired as instance method
LabeledStatement(node) {
this.visit(node.body);
}
ForStatement(node) {
// Create ForStatement declaration.
// NOTE: In ES6, ForStatement dynamically generates
// per iteration environment. However, escope is
// a static analyzer, we only generate one scope for ForStatement.
if (node.init && node.init.type === Syntax.VariableDeclaration && node.init.kind !== "var") {
this.scopeManager.__nestForScope(node);
}
this.visitChildren(node);
this.close(node);
}
ClassExpression(node) {
this.visitClass(node);
}
ClassDeclaration(node) {
this.visitClass(node);
}
CallExpression(node) {
// Check this is direct call to eval
if (!this.scopeManager.__ignoreEval() && node.callee.type === Syntax.Identifier && node.callee.name === "eval") {
// NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
// let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
this.currentScope().variableScope.__detectEval();
}
this.visitChildren(node);
}
BlockStatement(node) {
if (this.scopeManager.__isES6()) {
this.scopeManager.__nestBlockScope(node);
}
this.visitChildren(node);
this.close(node);
}
ThisExpression() {
this.currentScope().variableScope.__detectThis();
}
WithStatement(node) {
this.visit(node.object);
// Then nest scope for WithStatement.
this.scopeManager.__nestWithScope(node);
this.visit(node.body);
this.close(node);
}
VariableDeclaration(node) {
const variableTargetScope = (node.kind === "var") ? this.currentScope().variableScope : this.currentScope();
for (let i = 0, iz = node.declarations.length; i < iz; ++i) {
const decl = node.declarations[i];
this.visitVariableDeclaration(variableTargetScope, Variable.Variable, node, i);
if (decl.init) {
this.visit(decl.init);
}
}
}
// sec 13.11.8
SwitchStatement(node) {
this.visit(node.discriminant);
if (this.scopeManager.__isES6()) {
this.scopeManager.__nestSwitchScope(node);
}
for (let i = 0, iz = node.cases.length; i < iz; ++i) {
this.visit(node.cases[i]);
}
this.close(node);
}
FunctionDeclaration(node) {
this.visitFunction(node);
}
FunctionExpression(node) {
this.visitFunction(node);
}
ForOfStatement(node) {
this.visitForIn(node);
}
ForInStatement(node) {
this.visitForIn(node);
}
ArrowFunctionExpression(node) {
this.visitFunction(node);
}
ImportDeclaration(node) {
assert(this.scopeManager.__isES6() && this.scopeManager.isModule(), "ImportDeclaration should appear when the mode is ES6 and in the module context.");
const importer = new Importer(node, this);
importer.visit(node);
}
visitExportDeclaration(node) {
if (node.source) {
return;
}
if (node.declaration) {
this.visit(node.declaration);
return;
}
this.visitChildren(node);
}
// TODO: ExportDeclaration doesn't exist. for bc?
ExportDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportAllDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportDefaultDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportNamedDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportSpecifier(node) {
// TODO: `node.id` doesn't exist. for bc?
const local = (node.id || node.local);
this.visit(local);
}
MetaProperty() { // eslint-disable-line class-methods-use-this -- Desired as instance method
// do nothing.
}
JSXIdentifier(node) {
// Special case: "this" should not count as a reference
if (this.scopeManager.__isJSXEnabled() && node.name !== "this") {
this.currentScope().__referencing(node);
}
}
JSXMemberExpression(node) {
this.visit(node.object);
}
JSXElement(node) {
if (this.scopeManager.__isJSXEnabled()) {
this.visit(node.openingElement);
node.children.forEach(this.visit, this);
} else {
this.visitChildren(node);
}
}
JSXOpeningElement(node) {
if (this.scopeManager.__isJSXEnabled()) {
const nameNode = node.name;
const isComponentName = nameNode.type === "JSXIdentifier" && nameNode.name[0].toUpperCase() === nameNode.name[0];
const isComponent = isComponentName || nameNode.type === "JSXMemberExpression";
// we only want to visit JSXIdentifier nodes if they are capitalized
if (isComponent) {
this.visit(nameNode);
}
}
node.attributes.forEach(this.visit, this);
}
JSXAttribute(node) {
if (node.value) {
this.visit(node.value);
}
}
JSXExpressionContainer(node) {
this.visit(node.expression);
}
JSXNamespacedName(node) {
this.visit(node.namespace);
this.visit(node.name);
}
}
export default Referencer;
/* vim: set sw=4 ts=4 et tw=80 : */

View File

@@ -0,0 +1,171 @@
### Esrecurse [![Build Status](https://travis-ci.org/estools/esrecurse.svg?branch=master)](https://travis-ci.org/estools/esrecurse)
Esrecurse ([esrecurse](https://github.com/estools/esrecurse)) is
[ECMAScript](https://www.ecma-international.org/publications/standards/Ecma-262.htm)
recursive traversing functionality.
### Example Usage
The following code will output all variables declared at the root of a file.
```javascript
esrecurse.visit(ast, {
XXXStatement: function (node) {
this.visit(node.left);
// do something...
this.visit(node.right);
}
});
```
We can use `Visitor` instance.
```javascript
var visitor = new esrecurse.Visitor({
XXXStatement: function (node) {
this.visit(node.left);
// do something...
this.visit(node.right);
}
});
visitor.visit(ast);
```
We can inherit `Visitor` instance easily.
```javascript
class Derived extends esrecurse.Visitor {
constructor()
{
super(null);
}
XXXStatement(node) {
}
}
```
```javascript
function DerivedVisitor() {
esrecurse.Visitor.call(/* this for constructor */ this /* visitor object automatically becomes this. */);
}
util.inherits(DerivedVisitor, esrecurse.Visitor);
DerivedVisitor.prototype.XXXStatement = function (node) {
this.visit(node.left);
// do something...
this.visit(node.right);
};
```
And you can invoke default visiting operation inside custom visit operation.
```javascript
function DerivedVisitor() {
esrecurse.Visitor.call(/* this for constructor */ this /* visitor object automatically becomes this. */);
}
util.inherits(DerivedVisitor, esrecurse.Visitor);
DerivedVisitor.prototype.XXXStatement = function (node) {
// do something...
this.visitChildren(node);
};
```
The `childVisitorKeys` option does customize the behaviour of `this.visitChildren(node)`.
We can use user-defined node types.
```javascript
// This tree contains a user-defined `TestExpression` node.
var tree = {
type: 'TestExpression',
// This 'argument' is the property containing the other **node**.
argument: {
type: 'Literal',
value: 20
},
// This 'extended' is the property not containing the other **node**.
extended: true
};
esrecurse.visit(
ast,
{
Literal: function (node) {
// do something...
}
},
{
// Extending the existing traversing rules.
childVisitorKeys: {
// TargetNodeName: [ 'keys', 'containing', 'the', 'other', '**node**' ]
TestExpression: ['argument']
}
}
);
```
We can use the `fallback` option as well.
If the `fallback` option is `"iteration"`, `esrecurse` would visit all enumerable properties of unknown nodes.
Please note circular references cause the stack overflow. AST might have circular references in additional properties for some purpose (e.g. `node.parent`).
```javascript
esrecurse.visit(
ast,
{
Literal: function (node) {
// do something...
}
},
{
fallback: 'iteration'
}
);
```
If the `fallback` option is a function, `esrecurse` calls this function to determine the enumerable properties of unknown nodes.
Please note circular references cause the stack overflow. AST might have circular references in additional properties for some purpose (e.g. `node.parent`).
```javascript
esrecurse.visit(
ast,
{
Literal: function (node) {
// do something...
}
},
{
fallback: function (node) {
return Object.keys(node).filter(function(key) {
return key !== 'argument'
});
}
}
);
```
### License
Copyright (C) 2014 [Yusuke Suzuki](https://github.com/Constellation)
(twitter: [@Constellation](https://twitter.com/Constellation)) and other contributors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1 @@
module.exports={A:{A:{"1":"B","2":"K D E F mC","164":"A"},B:{"1":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"1":"0 9 MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC","2":"nC LC J PB qC rC","8":"1 2 3 4 5 6 7 8 K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB","328":"eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB"},D:{"1":"0 9 sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","2":"1 2 J PB K D E F A B C L M G N O P QB","8":"3 4 5 6 7 8 RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB","584":"pB qB rB"},E:{"1":"L M G xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","2":"J PB K sC SC tC","8":"D E F A B C uC vC wC TC FC","1096":"GC"},F:{"1":"0 fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z","2":"F B C 4C 5C 6C 7C FC kC 8C GC","8":"1 2 3 4 5 6 7 8 G N O P QB RB SB TB UB VB WB XB YB ZB aB bB","584":"cB dB eB"},G:{"1":"ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC","8":"E SC 9C lC AD BD CD DD ED FD GD HD ID JD KD LD","6148":"MD"},H:{"2":"WD"},I:{"1":"I","8":"LC J XD YD ZD aD lC bD cD"},J:{"8":"D A"},K:{"1":"H","2":"A","8":"B C FC kC GC"},L:{"1":"I"},M:{"1":"EC"},N:{"1":"B","36":"A"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 eD fD gD hD TC iD jD kD lD mD IC JC KC nD","2":"dD","8":"J"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"rD","328":"qD"}},B:2,C:"Pointer events",D:true};

View File

@@ -0,0 +1,263 @@
/**
* @fileoverview Translates tokens between Acorn format and Esprima format.
* @author Nicholas C. Zakas
*/
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
// none!
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
// Esprima Token Types
const Token = {
Boolean: "Boolean",
EOF: "<end>",
Identifier: "Identifier",
PrivateIdentifier: "PrivateIdentifier",
Keyword: "Keyword",
Null: "Null",
Numeric: "Numeric",
Punctuator: "Punctuator",
String: "String",
RegularExpression: "RegularExpression",
Template: "Template",
JSXIdentifier: "JSXIdentifier",
JSXText: "JSXText"
};
/**
* Converts part of a template into an Esprima token.
* @param {AcornToken[]} tokens The Acorn tokens representing the template.
* @param {string} code The source code.
* @returns {EsprimaToken} The Esprima equivalent of the template token.
* @private
*/
function convertTemplatePart(tokens, code) {
const firstToken = tokens[0],
lastTemplateToken = tokens.at(-1);
const token = {
type: Token.Template,
value: code.slice(firstToken.start, lastTemplateToken.end)
};
if (firstToken.loc) {
token.loc = {
start: firstToken.loc.start,
end: lastTemplateToken.loc.end
};
}
if (firstToken.range) {
token.start = firstToken.range[0];
token.end = lastTemplateToken.range[1];
token.range = [token.start, token.end];
}
return token;
}
/**
* Contains logic to translate Acorn tokens into Esprima tokens.
* @param {Object} acornTokTypes The Acorn token types.
* @param {string} code The source code Acorn is parsing. This is necessary
* to correct the "value" property of some tokens.
* @constructor
*/
function TokenTranslator(acornTokTypes, code) {
// token types
this._acornTokTypes = acornTokTypes;
// token buffer for templates
this._tokens = [];
// track the last curly brace
this._curlyBrace = null;
// the source code
this._code = code;
}
TokenTranslator.prototype = {
constructor: TokenTranslator,
/**
* Translates a single Esprima token to a single Acorn token. This may be
* inaccurate due to how templates are handled differently in Esprima and
* Acorn, but should be accurate for all other tokens.
* @param {AcornToken} token The Acorn token to translate.
* @param {Object} extra Espree extra object.
* @returns {EsprimaToken} The Esprima version of the token.
*/
translate(token, extra) {
const type = token.type,
tt = this._acornTokTypes;
if (type === tt.name) {
token.type = Token.Identifier;
// TODO: See if this is an Acorn bug
if (token.value === "static") {
token.type = Token.Keyword;
}
if (extra.ecmaVersion > 5 && (token.value === "yield" || token.value === "let")) {
token.type = Token.Keyword;
}
} else if (type === tt.privateId) {
token.type = Token.PrivateIdentifier;
} else if (type === tt.semi || type === tt.comma ||
type === tt.parenL || type === tt.parenR ||
type === tt.braceL || type === tt.braceR ||
type === tt.dot || type === tt.bracketL ||
type === tt.colon || type === tt.question ||
type === tt.bracketR || type === tt.ellipsis ||
type === tt.arrow || type === tt.jsxTagStart ||
type === tt.incDec || type === tt.starstar ||
type === tt.jsxTagEnd || type === tt.prefix ||
type === tt.questionDot ||
(type.binop && !type.keyword) ||
type.isAssign) {
token.type = Token.Punctuator;
token.value = this._code.slice(token.start, token.end);
} else if (type === tt.jsxName) {
token.type = Token.JSXIdentifier;
} else if (type.label === "jsxText" || type === tt.jsxAttrValueToken) {
token.type = Token.JSXText;
} else if (type.keyword) {
if (type.keyword === "true" || type.keyword === "false") {
token.type = Token.Boolean;
} else if (type.keyword === "null") {
token.type = Token.Null;
} else {
token.type = Token.Keyword;
}
} else if (type === tt.num) {
token.type = Token.Numeric;
token.value = this._code.slice(token.start, token.end);
} else if (type === tt.string) {
if (extra.jsxAttrValueToken) {
extra.jsxAttrValueToken = false;
token.type = Token.JSXText;
} else {
token.type = Token.String;
}
token.value = this._code.slice(token.start, token.end);
} else if (type === tt.regexp) {
token.type = Token.RegularExpression;
const value = token.value;
token.regex = {
flags: value.flags,
pattern: value.pattern
};
token.value = `/${value.pattern}/${value.flags}`;
}
return token;
},
/**
* Function to call during Acorn's onToken handler.
* @param {AcornToken} token The Acorn token.
* @param {Object} extra The Espree extra object.
* @returns {void}
*/
onToken(token, extra) {
const tt = this._acornTokTypes,
tokens = extra.tokens,
templateTokens = this._tokens;
/**
* Flushes the buffered template tokens and resets the template
* tracking.
* @returns {void}
* @private
*/
const translateTemplateTokens = () => {
tokens.push(convertTemplatePart(this._tokens, this._code));
this._tokens = [];
};
if (token.type === tt.eof) {
// might be one last curlyBrace
if (this._curlyBrace) {
tokens.push(this.translate(this._curlyBrace, extra));
}
return;
}
if (token.type === tt.backQuote) {
// if there's already a curly, it's not part of the template
if (this._curlyBrace) {
tokens.push(this.translate(this._curlyBrace, extra));
this._curlyBrace = null;
}
templateTokens.push(token);
// it's the end
if (templateTokens.length > 1) {
translateTemplateTokens();
}
return;
}
if (token.type === tt.dollarBraceL) {
templateTokens.push(token);
translateTemplateTokens();
return;
}
if (token.type === tt.braceR) {
// if there's already a curly, it's not part of the template
if (this._curlyBrace) {
tokens.push(this.translate(this._curlyBrace, extra));
}
// store new curly for later
this._curlyBrace = token;
return;
}
if (token.type === tt.template || token.type === tt.invalidTemplate) {
if (this._curlyBrace) {
templateTokens.push(this._curlyBrace);
this._curlyBrace = null;
}
templateTokens.push(token);
return;
}
if (this._curlyBrace) {
tokens.push(this.translate(this._curlyBrace, extra));
this._curlyBrace = null;
}
tokens.push(this.translate(token, extra));
}
};
//------------------------------------------------------------------------------
// Public
//------------------------------------------------------------------------------
export default TokenTranslator;

View File

@@ -0,0 +1,177 @@
# @eslint-community/regexpp
[![npm version](https://img.shields.io/npm/v/@eslint-community/regexpp.svg)](https://www.npmjs.com/package/@eslint-community/regexpp)
[![Downloads/month](https://img.shields.io/npm/dm/@eslint-community/regexpp.svg)](http://www.npmtrends.com/@eslint-community/regexpp)
[![Build Status](https://github.com/eslint-community/regexpp/workflows/CI/badge.svg)](https://github.com/eslint-community/regexpp/actions)
[![codecov](https://codecov.io/gh/eslint-community/regexpp/branch/main/graph/badge.svg)](https://codecov.io/gh/eslint-community/regexpp)
A regular expression parser for ECMAScript.
## 💿 Installation
```bash
$ npm install @eslint-community/regexpp
```
- require Node@^12.0.0 || ^14.0.0 || >=16.0.0.
## 📖 Usage
```ts
import {
AST,
RegExpParser,
RegExpValidator,
RegExpVisitor,
parseRegExpLiteral,
validateRegExpLiteral,
visitRegExpAST
} from "@eslint-community/regexpp"
```
### parseRegExpLiteral(source, options?)
Parse a given regular expression literal then make AST object.
This is equivalent to `new RegExpParser(options).parseLiteral(source)`.
- **Parameters:**
- `source` (`string | RegExp`) The source code to parse.
- `options?` ([`RegExpParser.Options`]) The options to parse.
- **Return:**
- The AST of the regular expression.
### validateRegExpLiteral(source, options?)
Validate a given regular expression literal.
This is equivalent to `new RegExpValidator(options).validateLiteral(source)`.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `options?` ([`RegExpValidator.Options`]) The options to validate.
### visitRegExpAST(ast, handlers)
Visit each node of a given AST.
This is equivalent to `new RegExpVisitor(handlers).visit(ast)`.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
### RegExpParser
#### new RegExpParser(options?)
- **Parameters:**
- `options?` ([`RegExpParser.Options`]) The options to parse.
#### parser.parseLiteral(source, start?, end?)
Parse a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"/abc/g"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression.
#### parser.parsePattern(source, start?, end?, flags?)
Parse a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"abc"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
- **Return:**
- The AST of the regular expression pattern.
#### parser.parseFlags(source, start?, end?)
Parse a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to parse. E.g. `"gim"`.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- **Return:**
- The AST of the regular expression flags.
### RegExpValidator
#### new RegExpValidator(options)
- **Parameters:**
- `options` ([`RegExpValidator.Options`]) The options to validate.
#### validator.validateLiteral(source, start, end)
Validate a regular expression literal.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
#### validator.validatePattern(source, start, end, flags)
Validate a regular expression pattern.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
- `flags?` (`{ unicode?: boolean, unicodeSets?: boolean }`) The flags to enable Unicode mode, and Unicode Set mode.
#### validator.validateFlags(source, start, end)
Validate a regular expression flags.
- **Parameters:**
- `source` (`string`) The source code to validate.
- `start?` (`number`) The start index in the source code. Default is `0`.
- `end?` (`number`) The end index in the source code. Default is `source.length`.
### RegExpVisitor
#### new RegExpVisitor(handlers)
- **Parameters:**
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
#### visitor.visit(ast)
Validate a regular expression literal.
- **Parameters:**
- `ast` ([`AST.Node`]) The AST to visit.
## 📰 Changelog
- [GitHub Releases](https://github.com/eslint-community/regexpp/releases)
## 🍻 Contributing
Welcome contributing!
Please use GitHub's Issues/PRs.
### Development Tools
- `npm test` runs tests and measures coverage.
- `npm run build` compiles TypeScript source code to `index.js`, `index.js.map`, and `index.d.ts`.
- `npm run clean` removes the temporary files which are created by `npm test` and `npm run build`.
- `npm run lint` runs ESLint.
- `npm run update:test` updates test fixtures.
- `npm run update:ids` updates `src/unicode/ids.ts`.
- `npm run watch` runs tests with `--watch` option.
[`AST.Node`]: src/ast.ts#L4
[`RegExpParser.Options`]: src/parser.ts#L743
[`RegExpValidator.Options`]: src/validator.ts#L220
[`RegExpVisitor.Handlers`]: src/visitor.ts#L291