acornjs / acorn-jsx Goto Github PK
View Code? Open in Web Editor NEWAlternative, faster React.js JSX parser
License: MIT License
Alternative, faster React.js JSX parser
License: MIT License
The Facebook JSX AST spec has recently changed. They now use JSXText
nodes instead of Literal
nodes to store strings inside of JSXElement
nodes.
https://github.com/facebook/jsx/blob/master/AST.md#jsx-text
This would be a breaking change, if Literal
was changed to JSXText
, but would allow this plugin to generate an AST that is more consistent with Babylon, Flow and ESPrima.
@RReverser
Is this something that you would consider changing?
The current code does not add support for the acorn walker utility.
I have a branch ready to submit as a PR, I just want your confirmation this would be merged before I start working on it.
Note that I would add this, but would not add the corresponding unit tests.
@RReverser I create this issue because I know you are working on official acorn. acorn-jsx is a copy/paste of the official acorn, but I tell me if acorn-jsx could extend acorn to customize it to support jsx in order to use last source of acorn.
I would like to provide a tern plugin for React inside Eclipse with https://github.com/angelozerr/tern.java but for that I need your work with acorn-jsx.
Debian project will appreciate if you tag the release on github.
Thank you
Consider this:
import React from 'react';
class OnOff extends React.Component {
render() {
return (
<input type="checkbox" id="onoff" />
<label for="onoff">Enable</label>
);
}
}
JSX compiler says Adjacent JSX elements must be wrapped in an enclosing tag but Babel prints Unexpected token (7:13). Also the token it refers to is for argument which is confusing because the actual issue is due to tags not having an ancestor.
See also babel/babel#1008 and gaearon/react-hot-boilerplate#16
I actually overlooked that #84 changed the type of the property value, but not the name of the property. JSXFragment
s should indeed have properties openingFragment
and closingFragment
, not openingElement
and closingElement
, see https://github.com/facebook/jsx/blob/master/AST.md#jsx-fragment.
Originally filed eslint/espree#355 but was told to file it here:
Currently we get a parsing error Unexpected token <
with this:
function* test() {
yield <Hey />;
}
However, if you use the babylon7 parser it works.
I used to just add parens around the JSX for this to work:
function* test() {
yield (<Hey />);
}
But it is now an issue when using eslint + eslint-plugin-prettier because prettier removes the parens and then eslint (using espree) gets a parsing error after that.
Hi,
is it possible to add acorn-es7-plugin to parse async/await function? Thanks
I'm using react-live, that uses buble behind the scenes.
Recently it seems that acorn
removed default export from their library. I think they did not follow semantic versioning properly, since this seems like a breaking change to consumers.
acorn-jsx
still relies on the default export to be present. And configures acorn
as a peerDependency.
See:
thanks for the amazing parser, I've got a Unexpected token (6:14)
when I want to parse a component having a class function, here is the code for it
import React from "react";
import PropTypes from "prop-types";
import "./Button.css";
class Button extends React.Component {
handleClick = () => {
this.props.clickHandler(this.props.name);
};
render() {
const className = [
"component-button",
this.props.orange ? "orange" : "",
this.props.wide ? "wide" : "",
];
return (
<div className={className.join(" ").trim()}>
<button onClick={this.handleClick}>{this.props.name}</button>
</div>
);
}
}
Button.propTypes = {
name: PropTypes.string,
orange: PropTypes.bool,
wide: PropTypes.bool,
clickHandler: PropTypes.func,
};
export default Button;
any way to fix this, thanks?
This parses fine:
var foo = {};
<TodoList someprop="someval" />
This fails:
var foo = {}
<TodoList someprop="someval" />
with the following exception:
./node_modules/acorn-jsx/node_modules/acorn/dist/acorn.js:2223
throw err
^
SyntaxError: Unexpected token (2:10)
Both cases should either fail or parse at the same time. But it does not seem like an easy fix might exist to this with a recursive-descent parser like acorn, since the grammar is ambiguous without a significant lookahead.
Sorry for the confusing title - if anyone can improve it please do.
This module claims to support both acorn^6.0.0
and acorn^7.0.0
:
Line 22 in e57398c
This may be correct in this particular module, but by allowing either one as a peer dependency, Node automatically pulls in the most recent one that is available. So if this plugin is being used in a project that still doesn't support acorn^7
but acorn^7
is included somewhere else in the dependency tree, the project will break because the versions conflict.
This is probably best explained with an example:
I've uploaded a basic module at https://github.com/iansan5653/simple-acorn-jsx-example/ that is a minimal example of a module that uses this extension and still runs acorn^6
. If you download this and run npm i
and node index
, the module will run just fine. As expected, npm installs the most recent version of acorn-jsx
and acorn^6.3.0
, and because acorn-jsx
does support acorn^6
, this works great.
However, if I require my example module in another project that uses acorn^7
, this is where problems occur. Here's an example of such a project:
package.json:
"dependencies": {
"acorn": "^7.0.0",
"simple-acorn-jsx-example": "github:iansan5653/simple-acorn-jsx-example"
}
}
index.js:
const result = require("simple-acorn-jsx-example")
console.log(result);
Running node index
here results in an error. This happens because acorn-jsx
finds acorn^7
in its peers and pulls that in instead of using the version of acorn found inside simple-acorn-jsx-example
.
A real-world impact of this is that any project which relies on Buble breaks if that project (or any of its dependencies) relies on acorn^7
. By extension, any project that uses styleguideist breaks under the same circumstances, because styleguideist relies on Buble.
Reference: styleguidist/react-styleguidist#1321.
I'm not sure exactly what solution works best here. Ideally acorn-jsx should check to see which version of acorn the requiring package is using and then adjust accordingly, but that may not be feasible.
Maybe there should be two releases of this plugin - one that is compatible with acorn^4
and one with acorn^5
. Maybe these could be two major versions of the same plugin? I'm not really sure.
Maybe there's a much more elegant solution I don't know about.
Please see acornjs/acorn#792
Hi, I just wanted to ask whether or not it would be possible to fully transpile the acorn-jsx export to IE friendly ES5 as it contains a class declaraction (line 72) return class extends Parser {
that when included in an IE11 project, causes IE11 to fail? If you're happy for me to, I can create a PR to do this?
If you want, I can provide more info. Regardless, I appreciate your time and work, thanks.
Since acorn-jsx
is a plugin for acorn
, acorn
can be made a peerDependency of acorn-jsx
. Would also solve #48.
Sorry if I'm missing something obvious, but is there a reason this shouldn't parse?:
export default <Somejsx />;
This does:
export default (<Somejsx />);
Same result with [email protected]
, with this of course:
{
ecmaVersion: 6,
sourceType: "module",
plugins: {
jsx: true
}
}
@RReverser I'm starting to develop a tern plugin for React https://github.com/angelozerr/tern-react
For the moment I can initialize acorn used inside tern with acorn-jsx.
As tern can work with Web Browser, I need to browserify the acorn-jsx. It should be very cool if you could do the same thing than acorn/dist by providing a file build-acorn_jsx.js like build-acorn.js.
Thanks!
I think it doesn't support sibling expression container like <div>{a}{b}</div>
after rewrite.
I added following test case to test/tests-jsx.js
. 'Unexpected token' error has occurred.
'<div>{a}{b}</div>': {
type: "ExpressionStatement",
start: 0,
end: 17,
expression: {
type: "JSXElement",
start: 0,
end: 17,
openingElement: {
type: "JSXOpeningElement",
start: 0,
end: 5,
attributes: [],
name: {
type: "JSXIdentifier",
start: 1,
end: 4,
name: "div"
},
selfClosing: false
},
closingElement: {
type: "JSXClosingElement",
start: 11,
end: 17,
name: {
type: "JSXIdentifier",
start: 13,
end: 16,
name: "div"
}
},
children: [{
type: 'JSXExpressionContainer',
expression: {
type: 'Identifier',
name: 'a',
range: [6, 7],
loc: {
start: {
line: 1,
column: 6
},
end: {
line: 1,
column: 7
}
}
},
range: [5, 8],
loc: {
start: {
line: 1,
column: 5
},
end: {
line: 1,
column: 8
}
}
}, {
type: 'JSXExpressionContainer',
expression: {
type: 'Identifier',
name: 'b',
range: [9, 10],
loc: {
start: {
line: 1,
column: 9
},
end: {
line: 1,
column: 10
}
}
},
range: [8, 11],
loc: {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 11
}
}
}
]
}
}
> node test/run.js
<div>{a}{b}</div> Unexpected token (1:11)
Normal parser: 899 tests run in 82ms; 1 failures.
Loose parser: 856 tests run in 117ms; all passed.
Total: 1755 tests run in 199ms; 1 failures.
npm ERR! Test failed. See above for more details.
npm ERR! not ok code 0
If static properties were found in code, parsing does not work correctly, JsxElements aren't parsed correctly anymore.
For example:
class B {} class A { static propTypes = { className: 1 }; render() { return ( <B></B> );}}
if propTypes statement if present, JsxElement 'B' isn't resolved correctly
Currently, eslint pulls in 2 versions of acorn because of this dep.
$ npm ls acorn
...
โโโฌ [email protected]
โโโฌ [email protected]
โโโ [email protected]
โโโฌ [email protected]
โโโ [email protected]
Does anyone know a javascript code generator that can take in an acorn-jsx ast and return a generated javascript code? Tried most of escodegen packages and plugins, with no luck.
Is it possible to provide a very simple sample babel plugin implementation wherever is the simplest and easiest for the author or a reference to the same possibly from the README? Thanks
Any chance this can be merged with the latest acorn?
acorn-jsx fails if you have a block within a function within a { } expression, like in the example below.
โฏ cat index.jsx
var foo = <div> {
function() {
if (true) {
}
}()
}
</div>;
โฏ jsx index.jsx
built Module("index.jsx")
var foo = React.createElement("div", null, " ",
function() {
if (true) {
}
}()
);
โฏ acorn-jsx index.jsx
Unexpected character '
' (4:5)
~/Projects/Testcases/6to5-react
โฏ
<a b={" "} c=" " d="&" e="id=1&group=2" f="�" g="{*;" h="&#x;" />
Current code fails due to the closing "
before removed from group=2"
as readXJSEntity()
will return undefined
when trying to find a HTML entity from &group=2...
.
In acornjs/acorn@f0cbb35 this was fixed:
let a
/regex/
The same issue exists with jsx and the parser is not able to parse this currently:
let a
<jsx />
This is a repost of babel/babel#419.
var Foo = React.createClass({
render() {
return (
<span>foo</span>
);
}
});
var Bar = React.createClass({
render() {
return (
<div>
<Foo/> bar
</div>
);
}
});
The whitespace between <Foo/>
and bar
is missing in the output.
6to5 fails compiling because of the slash ("/") after a tag.
This doesn't happen if we leave a space or a newline between them.
/** @jsx React.DOM */
var Component = React.createClass({
render: function () {
return (
<h1>/Authenticate</h1>
);
}
});
React.render(<Component />, document.body);
Issue originally reported in 6to5/6to5 as issue #398.
Not tested with acorn-jsx though.
@RReverser Would you be interested in supporting flow types? I think it'd be a good feature to add, especially since it can be used in conjunction with JSX. I can give this a go if this is something that you're interested in. Would be aiming to pass the entire esprima-fb type test suite.
Acorn have recently released a new major version: https://github.com/acornjs/acorn/releases/tag/7.0.0
Could you please bump your dependencies?
See JSX AST tree.
JSXSpreadChild
example: <div>{...children}</div>
.
Esprima has an open issue with the same problem.
I do not think I will be able to submit a PR for this though, but I still thought it might be beneficial to report the issue.
Excuse the convoluted example but take for example the following:
test.js
var React = require('react');
var Thing = React.createClass({
render() {
return (
<div>
<div>
<h1>foo</h1>
<p>foo</p>
<p>foo</p>
<p>foo</p>
<p>foo</p>
<p>foo</p>
<button onClick={this._handleClick}>click me</button>
</div>
</div>
);
},
_handleClick(event) {
var target = event.target;
console.log(target);
}
});
React.render(<Thing />, document.getElementById('main'));
If you get for example <button onClick={this._handleClick}>click me</button>
on line 14
:
> require("acorn-jsx").parse(require("fs").readFileSync("test.js", "utf8"), { ecmaVersion: 6, locations: true }).body[1].declarations[0].init.arguments[0].properties[0].value.body.body[0].argument.children[1].children[13].loc;
{ start: { line: 20, column: 20 },
end: { line: 20, column: 73 } }
As you can see the line number is completely off.
test should be released in order to test your package
Bastien for the debian project
See jsx-eslint/eslint-plugin-react#120
eslint-plugin-react depends on babel-core which depends on acorn-jsx.
Fix is to downgrade acorn-jsx to 1.0.3
When parsing this code:
<a>{/* this is a comment */}</a>;
The token for }
appears to have an incorrect range:
{ type:
{ label: '}',
keyword: undefined,
beforeExpr: false,
startsExpr: false,
isLoop: false,
isAssign: false,
prefix: false,
postfix: false,
binop: null,
updateContext: [Function] },
value: undefined,
start: 4,
end: 28 }
With a range of [4, 28]
, calling code.slice(token.start, token.end)
includes the comment before the }
. Is this intentional?
jsx of this form:
<path d="M94.4,42.1L74.1,61.8l4.8,27.9c0.1,0.4,0.1,0.7,0.1,1.1c0,1.5-0.7,2.8-2.3,2.8c-0.8,0-1.6-0.3-2.2-0.7
L49.4,79.8L24.4,93c-0.7,0.4-1.5,0.7-2.2,0.7c-1.6,0-2.3-1.3-2.3-2.8c0-0.4,0.1-0.7,0.1-1.1l4.8-27.9L4.4,42.1
C3.7,41.3,3,40.4,3,39.4c0-1.7,1.7-2.3,3.1-2.6l28-4.1L46.7,7.4c0.5-1.1,1.5-2.3,2.7-2.3s2.2,1.2,2.7,2.3l12.6,25.4l28,4.1
c1.3,0.2,3.1,0.9,3.1,2.6C95.9,40.4,95.1,41.3,94.4,42.1z" />
Throws a SyntaxError
Unterminated string constant (1:8)
This pattern of multiline string attributes is common in svg. It would be nice to use this syntax.
For now, you can workaround the issue by using a template string instead:
<path d={`M94.4,42.1L74.1,61.8l4.8,27.9c0.1,0.4,0.1,0.7,0.1,1.1c0,1.5-0.7,2.8-2.3,2.8c-0.8,0-1.6-0.3-2.2-0.7
L49.4,79.8L24.4,93c-0.7,0.4-1.5,0.7-2.2,0.7c-1.6,0-2.3-1.3-2.3-2.8c0-0.4,0.1-0.7,0.1-1.1l4.8-27.9L4.4,42.1
C3.7,41.3,3,40.4,3,39.4c0-1.7,1.7-2.3,3.1-2.6l28-4.1L46.7,7.4c0.5-1.1,1.5-2.3,2.7-2.3s2.2,1.2,2.7,2.3l12.6,25.4l28,4.1
c1.3,0.2,3.1,0.9,3.1,2.6C95.9,40.4,95.1,41.3,94.4,42.1z`} />
<div>
{
arr.map(item => <span>Some text</span>)
}
</div>
and eventually get
<div>
<span>Some text</span>
<span>Some text</span>
<span>Some text</span>
<span>Some text</span>
</div>
In Espree, we have this test case throwing an error (came from Esprima-FB originally):
<a.b:c></a.b:c>;
In Acorn-JSX, this parses okay. I'm assuming Acorn-JSX is correct, but just want to confirm that this is the correct behavior.
for example
let a = () => (
<>
<div>A</div>
<div>B</div>
<div>C</div>
</>
);
react fragments shot syntax is the snippet(<></>
) above
I have tried to implement a parser for finding all method calls with certain method names.
var acorn = require('acorn-jsx');
var walk = require('acorn/dist/walk');
var parsed = acorn.parse(code, {
ecmaVersion: 6,
plugins: {jsx: true}
});
walk.simple(parsed, {
CallExpression: (node) => {
doSomethingWithEveryCallExpressions(node);
}
});
But I only get this error:
TypeError: Object [object Object] has no method 'JSXElement'
at c (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:61:15)
at Object.skipThrough (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:180:3)
at c (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:61:15)
at Object.base.ReturnStatement.base.YieldExpression (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:223:22)
at c (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:61:15)
at Object.skipThrough (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:180:3)
at c (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:61:15)
at Object.base.Program.base.BlockStatement (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:191:5)
at c (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:61:15)
at Object.skipThrough (/Users/janmarek/www/shipito-client/node_modules/acorn/dist/walk.js:180:3)
Am I doing anything wrong or is it not possible to walk over AST with acorn/dist/walk?
It should be cool if acorn-jsx could support acorn_loose to give the capability to parse JSX which is not well formatted to use it for completion with https://github.com/angelozerr/tern-react
Since acorn is required from index.js, and acorn is not currently installed with NODE_ENV=production.
From acornjs/acorn#454 (comment).
If I enable this plugin, HTML comments come to trigger syntax errors.
"use strict";
var acorn = require('acorn-jsx');
var ast = acorn.parse(`
<!--
`.trim(), {plugins: {jsx: false}});
console.log(JSON.stringify(ast, null, 4));
{
"type": "Program",
"start": 0,
"end": 4,
"body": [],
"sourceType": "script"
}
"use strict";
var acorn = require('acorn-jsx');
var ast = acorn.parse(`
<!--
`.trim(), {plugins: {jsx: true}});
console.log(JSON.stringify(ast, null, 4));
C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\node_modules\acorn\dist\acorn.js:2223
throw err
^
SyntaxError: Unexpected token (1:1)
at Parser.pp$4.raise (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\node_modules\acorn\dist\acorn.js:2221:15)
at Parser.pp.unexpected (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\node_modules\acorn\dist\acorn.js:603:10)
at Parser.pp.jsx_parseIdentifier (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:191:12)
at Parser.pp.jsx_parseNamespacedName (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:200:21)
at Parser.pp.jsx_parseElementName (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:213:21)
at Parser.pp.jsx_parseOpeningElementAt (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:287:22)
at Parser.pp.jsx_parseElementAt (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:310:31)
at Parser.pp.jsx_parseElement (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:359:17)
at Parser.parseExprAtom (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\inject.js:381:23)
at Parser.pp$3.parseExprSubscripts (C:\Users\t-nagashima.AD\Documents\GitHub\acorn\node_modules\acorn-jsx\node_modules\acorn\dist\acorn.js:1715:21)
If there are HTML comments at places that JSXElements cannot exist, HTML comments don't trigger syntax errors.
"use strict";
var acorn = require('acorn-jsx');
var ast = acorn.parse(`
a<!--
`.trim(), {plugins: {jsx: true}});
console.log(JSON.stringify(ast, null, 4));
{
"type": "Program",
"start": 0,
"end": 5,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 1,
"expression": {
"type": "Identifier",
"start": 0,
"end": 1,
"name": "a"
}
}
],
"sourceType": "script"
}
Original report from downstream 6to5/acorn-6to5/issues/5:
The following all produce errors in the repl
var a = {} ;
var a = ({} );
var a = b({} );
var a = <div>{ {a} }</div>;
var a = <div {...a} ></div>;
I've traced it down to the line while (!eat(_braceR)) {
in the parseObj
function. I think adding skipSpace()
before the loop, and as the last thing in the loop, will fix the problem.
This test file is not under your copyright.
You violate the original BSD license by not adding license header on this test file.
Could you please do it
Bastien for the debian project
First, wanted to say thanks for working on this. I know the ESLint community really appreciates us supporting JSX out of the box!
We've run into the following issue on ESLint.
Running the following:
'use strict';
require('babel-register')({
presets: [ 'es2015' ]
});
var acorn = require('acorn-jsx/inject')(require('acorn'));
var ast = acorn.parse(
'<div {...this.props} />',
{
ecmaVersion: 5,
plugins: { jsx: true }
}
);
console.log(JSON.stringify(ast, null, 4));
yields the following:
/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:2223
throw err
^
SyntaxError: Unexpected token (1:6)
at Parser.pp$4.raise (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:2221:15)
at Parser.pp.unexpected (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:603:10)
at Parser.pp.expect (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:597:28)
at Parser.pp.jsx_parseAttribute (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn-jsx/inject.js:272:12)
at Parser.pp.jsx_parseOpeningElementAt (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn-jsx/inject.js:289:33)
at Parser.pp.jsx_parseElementAt (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn-jsx/inject.js:310:31)
at Parser.pp.jsx_parseElement (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn-jsx/inject.js:359:17)
at Parser.parseExprAtom (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn-jsx/inject.js:381:23)
at Parser.pp$3.parseExprSubscripts (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:1715:21)
at Parser.pp$3.parseMaybeUnary (/Users/kaicataldo/Code/test/acorn-test/node_modules/acorn/dist/acorn.js:1692:19)
From what I've read it looks like JSX Spread Attributes should be allowed in ES5, since it's part of the JSX spec. Does that sound right to you? If so, any idea if the fix would be in this plugin or in Acorn itself?
require("acorn-jsx").parse('<p>foo <a href="test">bar</a> baz</p>;').body[0].expression.children[2];
results in
{ type: 'Literal',
value: 'baz',
raw: 'baz'
when it should be:
{ type: 'Literal',
value: ' baz',
raw: ' baz'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.