Skip to content

Commit c0e8186

Browse files
committed
Merge remote-tracking branch 'mysticatea/master'
* mysticatea/master: 2.0.1 Fix: follow tc39/ecma262#910 (refs eslint/eslint#10861) 2.0.0 2.0.0-beta.0 Update: Unicode version to 11 Breaking: replace Disjunction node by Alternative node Docs: update README.md Chore: trivial Chore: follow up mysticatea#2 Update: parseRegExpLiteral supports RegExp object Chore: coverage Chore: upgrade deps Fix: location of quantifier (fixes mysticatea#3) New: add visitor Chore: update eslint config Breaking: drop Node.js 4 support # Conflicts: # .eslintignore # .eslintrc.yml # package.json # src/index.ts # src/parser.ts # test/fixtures/parser/literal.ts # tsconfig.json
2 parents b027a46 + d68b435 commit c0e8186

32 files changed

+37592
-21275
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
/.nyc_output
12
/.temp
3+
/coverage
24
/node_modules
35
/test.*
46
### git template

.nycrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"include": ["src/**/*.ts"],
3+
"exclude": ["src/unicode/*.ts"],
4+
"extension": [".ts"],
5+
"require": ["ts-node/register"]
6+
}

.travis.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ sudo: false
22

33
language: node_js
44
node_js:
5-
- "4"
6-
- "6"
5+
- "6.5"
76
- "8"
8-
- "9"
7+
- "10"
8+
9+
after_success:
10+
- npm run coveralls

README.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![npm version](https://img.shields.io/npm/v/regexpp.svg)](https://www.npmjs.com/package/regexpp)
44
[![Downloads/month](https://img.shields.io/npm/dm/regexpp.svg)](http://www.npmtrends.com/regexpp)
55
[![Build Status](https://travis-ci.org/mysticatea/regexpp.svg?branch=master)](https://travis-ci.org/mysticatea/regexpp)
6+
[![Coverage Status](https://coveralls.io/repos/github/mysticatea/regexpp/badge.svg)](https://coveralls.io/github/mysticatea/regexpp)
67
[![Dependency Status](https://david-dm.org/mysticatea/regexpp.svg)](https://david-dm.org/mysticatea/regexpp)
78

89
The regular expression parser for ECMAScript.
@@ -13,7 +14,7 @@ The regular expression parser for ECMAScript.
1314
$ npm install regexpp
1415
```
1516

16-
- require Node.js 4.0.0 or newer.
17+
- require Node.js 6.5.0 or newer.
1718

1819
## 📖 Usage
1920

@@ -22,8 +23,10 @@ import {
2223
AST,
2324
RegExpParser,
2425
RegExpValidator,
26+
RegExpVisitor,
2527
parseRegExpLiteral,
2628
validateRegExpLiteral,
29+
visitRegExpAST
2730
} from "regexpp"
2831
```
2932

@@ -34,7 +37,7 @@ Parse a given regular expression literal then make AST object.
3437
This is equivalent to `new RegExpParser(options).parseLiteral(source)`.
3538

3639
- **Parameters:**
37-
- `source` (`string`) The source code to parse.
40+
- `source` (`string | RegExp`) The source code to parse.
3841
- `options?` ([`RegExpParser.Options`]) The options to parse.
3942
- **Return:**
4043
- The AST of the regular expression.
@@ -49,6 +52,16 @@ This is equivalent to `new RegExpValidator(options).validateLiteral(source)`.
4952
- `source` (`string`) The source code to validate.
5053
- `options?` ([`RegExpValidator.Options`]) The options to validate.
5154

55+
### visitRegExpAST(ast, handlers)
56+
57+
Visit each node of a given AST.
58+
59+
This is equivalent to `new RegExpVisitor(handlers).visit(ast)`.
60+
61+
- **Parameters:**
62+
- `ast` ([`AST.Node`]) The AST to visit.
63+
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
64+
5265
### RegExpParser
5366

5467
#### new RegExpParser(options?)
@@ -125,6 +138,20 @@ Validate a regular expression flags.
125138
- `start?` (`number`) The start index in the source code. Default is `0`.
126139
- `end?` (`number`) The end index in the source code. Default is `source.length`.
127140

141+
### RegExpVisitor
142+
143+
#### new RegExpVisitor(handlers)
144+
145+
- **Parameters:**
146+
- `handlers` ([`RegExpVisitor.Handlers`]) The callbacks.
147+
148+
#### visitor.visit(ast)
149+
150+
Validate a regular expression literal.
151+
152+
- **Parameters:**
153+
- `ast` ([`AST.Node`]) The AST to visit.
154+
128155
## 📰 Changelog
129156

130157
- [GitHub Releases](https://github.com/mysticatea/regexpp/releases)
@@ -145,5 +172,7 @@ Please use GitHub's Issues/PRs.
145172
- `npm run update:ids` updates `src/unicode/ids.ts`.
146173
- `npm run watch` runs tests with `--watch` option.
147174

148-
[`RegExpParser.Options`]: src/parser.ts#L527
175+
[`AST.Node`]: src/ast.ts#L4
176+
[`RegExpParser.Options`]: src/parser.ts#L539
149177
[`RegExpValidator.Options`]: src/validator.ts#L127
178+
[`RegExpVisitor.Handlers`]: src/visitor.ts#L204

rollup.config.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import resolve from "rollup-plugin-node-resolve"
2+
import sourcemaps from "rollup-plugin-sourcemaps"
3+
4+
export default [
5+
{
6+
input: ".temp/index.js",
7+
output: {
8+
file: "index.js",
9+
format: "cjs",
10+
sourcemap: true,
11+
sourcemapFile: "index.js.map",
12+
banner: `/*! @author Toru Nagashima <https://github.com/mysticatea> */`,
13+
},
14+
plugins: [sourcemaps(), resolve()],
15+
},
16+
{
17+
input: ".temp/index.js",
18+
output: {
19+
file: "index.mjs",
20+
format: "es",
21+
sourcemap: true,
22+
sourcemapFile: "index.mjs.map",
23+
banner: `/*! @author Toru Nagashima <https://github.com/mysticatea> */`,
24+
},
25+
plugins: [sourcemaps(), resolve()],
26+
},
27+
]

tools/clone-without-circular.ts renamed to scripts/clone-without-circular.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const relative = require("path").posix.relative
22

33
function resolveLocation(
4-
obj: object,
4+
obj: any,
55
path: string[],
66
pathMap: Map<object, string>,
77
): void {
@@ -38,7 +38,7 @@ function cloneWithoutCircularRec(x: any, pathMap: Map<object, string>): any {
3838
return x.map(el => cloneWithoutCircularRec(el, pathMap))
3939
}
4040

41-
const y = {}
41+
const y = {} as any
4242
for (const key of Object.keys(x)) {
4343
if (key === "parent" || key === "resolved" || key === "references") {
4444
y[key] = getRelativePath(x, x[key], pathMap)

scripts/update-fixtures.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { AST, parseRegExpLiteral, visitRegExpAST } from "../src/index"
2+
import * as Parser from "../test/fixtures/parser/literal"
3+
import * as Visitor from "../test/fixtures/visitor"
4+
import { cloneWithoutCircular } from "./clone-without-circular"
5+
6+
for (const filename of Object.keys(Parser.Fixtures)) {
7+
const fixture = Parser.Fixtures[filename]
8+
const options = fixture.options
9+
10+
for (const pattern of Object.keys(fixture.patterns)) {
11+
try {
12+
const ast = parseRegExpLiteral(pattern, options)
13+
fixture.patterns[pattern] = { ast: cloneWithoutCircular(ast) }
14+
} catch (err) {
15+
fixture.patterns[pattern] = {
16+
error: { message: err.message, index: err.index },
17+
}
18+
}
19+
}
20+
21+
Parser.save()
22+
}
23+
24+
for (const filename of Object.keys(Visitor.Fixtures)) {
25+
const fixture = Visitor.Fixtures[filename]
26+
const options = fixture.options
27+
28+
for (const pattern of Object.keys(fixture.patterns)) {
29+
const ast = parseRegExpLiteral(pattern, options)
30+
const history = [] as string[]
31+
const enter = (node: AST.Node): void => {
32+
history.push(`enter:${node.type}:${node.raw}`)
33+
}
34+
const leave = (node: AST.Node): void => {
35+
history.push(`leave:${node.type}:${node.raw}`)
36+
}
37+
38+
visitRegExpAST(ast, {
39+
onAlternativeEnter: enter,
40+
onAssertionEnter: enter,
41+
onBackreferenceEnter: enter,
42+
onCapturingGroupEnter: enter,
43+
onCharacterEnter: enter,
44+
onCharacterClassEnter: enter,
45+
onCharacterClassRangeEnter: enter,
46+
onCharacterSetEnter: enter,
47+
onFlagsEnter: enter,
48+
onGroupEnter: enter,
49+
onPatternEnter: enter,
50+
onQuantifierEnter: enter,
51+
onRegExpLiteralEnter: enter,
52+
onAlternativeLeave: leave,
53+
onAssertionLeave: leave,
54+
onBackreferenceLeave: leave,
55+
onCapturingGroupLeave: leave,
56+
onCharacterLeave: leave,
57+
onCharacterClassLeave: leave,
58+
onCharacterClassRangeLeave: leave,
59+
onCharacterSetLeave: leave,
60+
onFlagsLeave: leave,
61+
onGroupLeave: leave,
62+
onPatternLeave: leave,
63+
onQuantifierLeave: leave,
64+
onRegExpLiteralLeave: leave,
65+
})
66+
67+
fixture.patterns[pattern] = history
68+
}
69+
70+
Visitor.save()
71+
}

tools/update-unicode-ids.ts renamed to scripts/update-unicode-ids.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ enum Mode {
1717

1818
// Main
1919
;(async () => {
20-
let banner: string = ""
20+
let banner = ""
2121
const idStartSet: Set<string> = new Set()
2222
const idStartSmall: Array<[number, number]> = []
2323
const idStartLarge: Array<[number, number]> = []
@@ -26,7 +26,7 @@ enum Mode {
2626

2727
logger.log("Fetching data... (%s)", DB_URL)
2828
await processEachLine(line => {
29-
let m: RegExpExecArray //eslint-disable-line init-declarations
29+
let m: RegExpExecArray | null = null
3030
if (banner === "") {
3131
logger.log("Processing data... (%s)", line.slice(2))
3232
banner = `/* Generated from ${line.slice(2)} */`
@@ -68,7 +68,10 @@ ${makeCondition(idContinueLarge, Mode.Former)}
6868
}`
6969

7070
logger.log("Formatting code...")
71-
const engine = new CLIEngine({ fix: true })
71+
const engine = new CLIEngine({
72+
fix: true,
73+
rules: { curly: "off" },
74+
})
7275
const result = engine.executeOnText(code, "ids.ts").results[0]
7376
code = result.output || code
7477

@@ -92,7 +95,7 @@ function processEachLine(cb: (line: string) => void): Promise<void> {
9295
if (lines.length === 1) {
9396
buffer = lines[0]
9497
} else {
95-
buffer = lines.pop()
98+
buffer = lines.pop()!
9699
for (const line of lines) {
97100
cb(line)
98101
}

0 commit comments

Comments
 (0)