react-sentence-tree
Version:
Create sentence trees with this react component
274 lines (206 loc) • 32.7 kB
Markdown
<p align="center">
<h3 align="center">React Sentence Tree</h3>
<p align="center">
Quickly visualize sentences in a Tree Diagram
<br />
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree-demo" target="_blank">View Demo</a>
·
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree/issues" target="_blank">Report Bug</a>
·
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree/issues" target="_blank">Request Feature</a>
</p>
<div align="center">
<a href="https://badge.fury.io/js/react-sentence-tree" target="_blank" rel="noopener noreferrer"><img src="https://badge.fury.io/js/react-sentence-tree.svg" alt="npm version" height="18"></a>
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree//network/members" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/github/forks/Lucas-Kohorst/react-sentence-tree?style=social"></img></a>
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree//stargazers" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/github/stars/Lucas-Kohorst/react-sentence-tree?style=social"></img></a>
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree//issues" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/github/issues/Lucas-Kohorst/react-sentence-tree"></img></a>
<a href="https://github.com/Lucas-Kohorst/react-sentence-tree/blob/master/LICENSE" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/l/react-sentence-tree"></img></a>
<a href="https://linkedin.com/in/lucaskohorst" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555"></img></a>
</div>
</p>
<!-- TABLE OF CONTENTS -->
## Table of Contents
* [Quick Start](#quick-start)
* [Failed to Compile](#failed-to-compile)
* [About the Project](#about-the-project)
* [Built With](#built-with)
* [Getting Started](#getting-started)
* [Installation](#Install)
* [Configuring StanfordNLP](#StanfordNLP)
* [Documentation](#documentation)
* [Roadmap](#roadmap)
* [Contributing](#contributing)
* [License](#license)
* [Contact](#contact)
* [Acknowledgements](#acknowledgements)
## Quick Start
This is a react component that will render constituency/syntactical and dependency trees based on sentence input
#### 1. Install
```npm i react-sentence-tree```
#### 2. Import
```import { SentenceTree } from 'react-sentence-tree```
#### Start a Stanford CoreNLP Server
Stanford CoreNLP can by downloaded and ran through npm thanks to [CoreNLP @gerardobort](https://www.npmjs.com/package/corenlp). If you want to [compile from sources see below](#StandfordNLP)
```
npm explore corenlp -- npm run corenlp:download
```
Once downloaded you can easily start the server by running
```bash
npm explore corenlp -- npm run corenlp:server
```
#### 3. Render
```
// Custom sentence
<SentenceTree sentence="The little dog ran fast">
// Dependency Tree
<SentenceTree type={"dependency"} textbox=true>
// Textbox for user input
<SentenceTree textbox=true>
```
## Failed to Compile
If you receive this error an error similar to
```
./node_modules/corenlp/dist/connector/connector-server.js
Module not found: Can't resolve 'request-promise-native' in '/<filepath>/node_modules/corenlp/dist/connector'
```
Don't worry this can easily be fixed by opening ```/<filepath>/node_modules/corenlp/dist/package.json``` and changing the following line
```
"request-promise-native": "./src/polyfills/request-promise-native.js",
```
to
```
"request-promise-native": "./dist/polyfills/request-promise-native.js",
```
I have opened a [pull request](https://github.com/gerardobort/node-corenlp/pull/56) for this as well.
Now the package should work. If you are still having problems open an [issue](https://github.com/Lucas-Kohorst/react-sentence-tree//issues)
or [contact me](#contact)
<!-- ABOUT THE PROJECT -->
## About The Project
This react component provides an easy way to the constituency/syntactical structure or dependency tree of a sentence.
### Built With
* [React](https://github.com/facebook/react)
* [CoreNLP - NPM](https://www.npmjs.com/package/corenlp)
* [react-d3-Tree](https://www.npmjs.com/package/react-d3-tree)
<!-- GETTING STARTED -->
## Getting Started
## Install
```npm i react-sentence-tree```
## Import
```import { SentenceTree } from 'react-sentence-tree```
## StanfordNLP
Credits to [CoreNLP @gerardobort](https://www.npmjs.com/package/corenlp)
##### Download Stanford CoreNLP
##### Shortcut
Via `npm`, run this command from your own project after having installed this library:
```
npm explore corenlp -- npm run corenlp:download
```
Once downloaded you can easily start the server by running
```
npm explore corenlp -- npm run corenlp:server
```
Or you can manually download the project from the Stanford's CoreNLP download section at: https://stanfordnlp.github.io/CoreNLP/download.html
You may want to download, apart of the full package, other language models (see more on that page).
##### Via sources
For advanced projects, when you have to customize the library a bit more, we highly recommend to download the StanfordCoreNLP from the [original repository](https://github.com/stanfordnlp/CoreNLP), and compile the source code by using `ant jar`.
##### Configure Stanford CoreNLP
There are two method to connect your NodeJS application to Stanford CoreNLP:
1. HTTP is the preferred method since it requires CoreNLP to initialize just once to serve many requests, it also avoids extra I/O given that the CLI method need to write temporary files to run *recommended*.
2. Via Command Line Interface, this is by spawning processes from your app.
##### Using StanfordCoreNLPServer
```bash
# Run the server using all jars in the current directory (e.g., the CoreNLP home directory)
java -mx4g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -port 9000 -timeout 15000
```
CoreNLP connects by default via StanfordCoreNLPServer, using port 9000. You can also opt to setup the connection differently:
You can configure the corenlp port in [utils/Tree.js](https://github.com/Lucas-Kohorst/react-sentence-tree/blob/master/src/utils/Tree.js)
```
import CoreNLP, { Properties, Pipeline, ConnectorServer } from 'corenlp';
// Configure to port of your choosing 9000 default
const connector = new ConnectorServer({ dsn: 'http://localhost:9000' });
// Pass it into the pipeline
const pipeline = new Pipeline(props, "English", connector);
```
## 4. Usage
```
// Custom sentence
<SentenceTree sentence="The little dog ran fast">
// Dependency Tree
<SentenceTree type={"dependency"} textbox=true>
// Textbox for user input
<SentenceTree textbox=true>
// @todo Add more usage examples
```
<!-- Documentation -->
## Documentation
#### Sentence Props
| **Property** | **Type** | **Required?** | **Options** | **Default** | **Description** |
|--------------|----------|---------------|-------------------------------------------------------------|------------------------------------|---------------------------------------------------|
| sentence | string | | | "I shot an elephant in my pajamas" | The sentence that you wish to parse |
| type | string | | "constituency", "dependency" | constituency | The type of tree you want to generate |
| textField | boolean | | true, false | false | If you want to render a text field for user input |
| language | string | | see https://github\.com/stanfordnlp/CoreNLP\#latest\-models | "English" | The language you want to parse |
#### Tree Props
Credits to [react-d3-tree @bkrem](https://www.npmjs.com/package/react-d3-tree)
| Property | Type | Options | Required? | Default | Description |
|:------------------------------|:-----------------------|:---------------------------------------------------------------------------------------|:----------|:--------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `data` | `array`<br/>`object` | | required | `undefined` | Single-element array containing the root node object (see `myTreeData` above). <br/> Passing the root node object without an array wrapping it is also possible. <br /><br /> `react-d3-tree` will automatically attach a unique `id` attribute to each node in the DOM, as well as `data-source-id` & `data-target-id` attributes to each link connecting two nodes. |
| `nodeSvgShape` | `object` | see [Node shapes](#node-shapes) | | `{shape: 'circle', shapeProps: {r: 10}}` | Sets a specific SVG shape element + shapeProps to be used for each node. |
| `nodeLabelComponent` | `object` | see [Using foreignObjects](#using-foreignobjects) | | `null` | Allows using a React component as a node label; requires `allowForeignObjects` to be set. |
| `onClick` | `func` | | | `undefined` | Callback function to be called when a node is clicked. <br /><br />Has the function signature `(nodeData, evt)`. The clicked node's data object is passed as first parameter, event object as second. |
| `onMouseOver` | `func` | | | `undefined` | Callback function to be called when mouse enters the space belonging to a node. <br /><br />Has the function signature `(nodeData, evt)`. The clicked node's data object is passed as first parameter, event object as second. |
| `onMouseOut` | `func` | | | `undefined` | Callback function to be called when mouse leaves the space belonging to a node. <br /><br />Has the function signature `(nodeData, evt)`. The clicked node's data object is passed as first parameter, event object as second. |
| `onLinkClick` | `func` | | | `undefined` | Callback function to be called when a link is clicked. <br /><br />Has the function signature `(linkSource, linkTarget, evt)`. The clicked link's parent data object is passed as first parameter, the child's as second, the event object as third. |
| `onLinkMouseOver` | `func` | | | `undefined` | Callback function to be called when mouse enters the space belonging to a link. <br /><br />Has the function signature `(linkSource, linkTarget, evt)`. The clicked link's parent data object is passed as first parameter, the child's as second, the event object as third. |
| `onLinkMouseOut` | `func` | | | `undefined` | Callback function to be called when mouse leaves the space belonging to a link. <br /><br />Has the function signature `(linkSource, linkTarget, evt)`. The clicked link's parent data object is passed as first parameter, the child's as second, the event object as third. |
| `onUpdate` | `func` | | | `undefined` | Callback function to be called when the inner D3 component updates. That is - on every zoom or translate event, or when tree branches are toggled. <br /><br />Has the function signature `(updateTarget: {targetNode, currentTranslate, currentZoom})`. |
| `orientation` | `string` (enum) | `horizontal` `vertical` | | `horizontal` | `horizontal` - Tree expands left-to-right. <br /><br /> `vertical` - Tree expands top-to-bottom. |
| `translate` | `object` | | | `{x: 0, y: 0}` | Translates the graph along the x/y axis by the specified amount of pixels (avoids the graph being stuck in the top left canvas corner). |
| `pathFunc` | `string (enum)`/`func` | `diagonal`<br/>`elbow`<br/>`straight`<br/>`customFunc(linkData, orientation)` | | `diagonal` | `diagonal` - Smooth, curved edges between parent-child nodes. <br /><br /> `elbow` - Sharp edges at right angles between parent-child nodes. <br /><br /> `straight` - Straight lines between parent-child nodes. <br /><br /> `customFunc` - Custom draw function that accepts `linkData` as its first param and `orientation` as its second. |
| `collapsible` | `bool` | | | `true` | Toggles ability to collapse/expand the tree's nodes by clicking them. |
| `useCollapseData` | `bool` | see [Pre-defining a node's `_collapsed` state](#pre-defining-a-nodes-_collapsed-state) | | `false` | Toggles whether the tree should automatically use any `_collapsed: bool` properties it finds on nodes in the passed data set to configure its initial layout. |
| `shouldCollapseNeighborNodes` | `bool` | | | `false` | If a node is currently being expanded, all other nodes at the same depth will be collapsed. |
| `initialDepth` | `number` | `0..n` | | `undefined` | Sets the maximum node depth to which the tree is expanded on its initial render. <br /> Tree renders to full depth if prop is omitted. |
| `depthFactor` | `number` | `-n..0..n` | | `undefined` | Ensures the tree takes up a fixed amount of space (`node.y = node.depth * depthFactor`), regardless of tree depth. <br /> **TIP**: Negative values invert the tree's direction. |
| `zoomable` | `bool` | | | `true` | Toggles ability to zoom in/out on the Tree by scaling it according to `props.scaleExtent`. |
| `zoom` | `number` | `0..n` | | `1` | A floating point number to set the initial zoom level. It is constrained by `props.scaleExtent`. `1` is the default "non-zoomed" level. |
| `scaleExtent` | `object` | `{min: 0..n, max: 0..n}` | | `{min: 0.1, max: 1}` | Sets the minimum/maximum extent to which the tree can be scaled if `props.zoomable` is true. |
| `nodeSize` | `object` | `{x: 0..n, y: 0..n}` | | `{x: 140, y: 140}` | Sets a fixed size for each node. <br /><br /> This does not affect node circle sizes, circle sizes are handled by the `circleRadius` prop. |
| `separation` | `object` | `{siblings: 0..n, nonSiblings: 0..n}` | | `{siblings: 1, nonSiblings: 2}` | Sets separation between neighbouring nodes, differentiating between siblings (same parent) and non-siblings. |
| `transitionDuration` | `number` | `0..n` | | `500` | Sets the animation duration (in ms) of each expansion/collapse of a tree node. <br /><br /> Set this to `0` to deactivate animations completely. |
| `textLayout` | `object` | `{textAnchor: enum, x: -n..0..n, y: -n..0..n, transform: string}` | | `{textAnchor: "start", x: 10, y: -10, transform: undefined }` | Configures the positioning of each node's text (name & attributes) relative to the node itself. Defining a `textLayout` property on a node passed in `props.data` will override this global configuration for that node.<br/><br/>`textAnchor` enums mirror the [`text-anchor` spec](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor).<br/><br/>`x` & `y` accept integers denoting `px` values.<br/><br/> `transform` mirrors the [svg `transform` spec](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform). |
| `styles` | `object` | see [Styling](#styling) | | `Node`/`Link` CSS files | Overrides and/or enhances the tree's default styling. |
| `allowForeignObjects` | `bool` | see [Using foreignObjects](#using-foreignobjects) | | `false` | Allows use of partially supported `<foreignObject />` elements. |
| `circleRadius` (legacy) | `number` | `0..n` | | `undefined` | Sets the radius of each node's `<circle>` element.<br /><br /> **Will be deprecated in v2, please use `nodeSvgShape` instead.** |
<!-- ROADMAP -->
## Roadmap
See the [open issues](https://github.com/Lucas-Kohorst/react-sentence-tree/issues) for a list of proposed features (and known issues).
<!-- CONTRIBUTING -->
## Contributing
Feel free to fork, open pull requests and contribute to this project
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/<feature>`)
3. Commit your Changes (`git commit -m 'Useful description of the feature'`)
4. Push to the Branch (`git push origin feature/<feature>`)
5. Open a Pull Request
<!-- LICENSE -->
## License
Distributed under the MIT License. See `LICENSE` for more information.
<!-- CONTACT -->
## Contact
[@KohorstLucas](https://twitter.com/KohoestLucas)<br />
[kohorstlucas@gmail.com](mailto:kohorstlucas@gmail.com)
<!-- ACKNOWLEDGEMENTS -->
## Research and Acknowledgments
### Research
* [Penn Treeebank Constitutes](http://surdeanu.info/mihai/teaching/ista555-fall13/readings/PennTreebankConstituents.html)
* [Stanford NLP Parser](https://nlp.stanford.edu/software/lex-parser.shtml)
* [A Fundamental Algorithm for Dependency Parsing](http://web.stanford.edu/~mjkay/covington.pdf)
* [Tree Syntax of Natural Language](cs.cornell.edu/courses/cs474/2004fa/lec1.pdf)
* [Constituency vs. Dependency Parsing](http://www.ruslang.ru/doc/melchuk_festschrift2012/Kahane.pdf.)
* [Constituency Parsing](https://web.stanford.edu/~jurafsky/slp3/13.pdf.)
* [Dependency Parsing](https://web.stanford.edu/~jurafsky/slp3/15.pdf.)
* [Ideas for hard to parse sentences](https://www.reddit.com/r/LanguageTechnology/comments/dlj40d/what_are_some_of_the_hardest_types_or_examples_of/.)
### Packages
* [react-d3-tree @bkrem](https://www.npmjs.com/package/react-d3-tree)
* [CoreNLP @gerardobort](https://www.npmjs.com/package/corenlp)