GithubHelp home page GithubHelp logo

allenai / hierplane Goto Github PK

View Code? Open in Web Editor NEW
82.0 14.0 14.0 640 KB

A tool for visualizing trees, tailored specifically to the analysis of parse trees.

Home Page: https://allenai.github.io/hierplane/

License: Apache License 2.0

JavaScript 57.99% HTML 0.31% CSS 41.70%

hierplane's Introduction

Hierplane

A javascript library for visualizing hierarchical data, specifically tailored towards rendering dependency parses.

Table of Contents

Usage

There are two ways to use hierplane:

In a web page:

Add the following <script> tag to your web page:

<script src="//unpkg.com/hierplane/dist/static/hierplane.min.js"></script>

Add the following styles to your web page, likely in the <head /> tag:

<link rel="stylesheet" type="text/css" href="//unpkg.com/hierplane/dist/static/hierplane.min.css">

Then invoke hierplane.renderTree(tree[, options]) as is desired.

- `tree` *object* the tree to visualize, see <a href="#tree-structure">a detailed description of
 the tree structure.</a>
- `options` *object* optional overrides
    - `options.theme` *string* the theme to use, one of 'dark' or 'light', 
       defaults to 'dark'.
    - `options.target` *string* a css selector targeting the element where
      the resulting DOM should be rendered, defaults to 'body'.

The renderTree() method returns a function that will unmount the rendered content, if you want to remove the visualization:

const unmount = hierplane.renderTree(tree, { target: '#hierplane', theme: 'light' });
// Don't do this
const target = document.getElementById('hierplane');
target.removeChild(target.firstElementChild);
// Do this
unmount();

You can see a full example here.

In a web application that uses ReactJS:

Install the hierplane dependency:

npm install --save hierplane

Then, simply import the Tree component, and pass it the tree you'd like to render:

import { Tree } from 'hierplane';
import React from 'react';

const aTree = { ... };

class TreeContainer extends React.PureComponent {
  render() {
    return <Tree tree={aTree} />;
  }
}

Tree Structure

A tree is an object with the following structure:

/**
 * @type object
 */
Tree
  /**
   * The text being visualized.
   * @type string
   * @required
   */
  text: 'Sam likes eating hot dogs.'
  /**
   * Map used to apply node styles (see `Style Maps` section).
   * @type object
   * @optional
   */
  nodeTypeToStyle: { ... }
  /**
   * Map used to set node positioning (see `Style Maps` section).
   * @type object
   * @optional
   */
  linkToPosition: { ... }
  /**
   * Map used to override link labels (see `Style Maps` section).
   * @type object
   * @optional
   */
  linkNameToLabel: { ... }
  /**
   * The root node of the tree.
   * @type object
   * @required
   */
  root: Node { ... }

The root property refers to the root node of the tree to be visualized. Each node has the following structure:

/**
 * @type object
 */
Node
  /**
   * The text content of the node
   * @type string
   * @required
   *
   * TODO: This will likely be migrated to be named `text` in a future version, as it's less specific.
   */
  word: 'eating'
  /**
   * A string specifying the "type" of node. This is used to determine it's color -- all nodes of
   * the same type will be assigned the same color.
   * @type string
   * @required
   */
  nodeType: 'verb'
  /**
   * A string specifying describing the relationship between the node and it's parent. This text
   * will be displayed on an element connecting the node and it's parent.
   * @type string
   * @optional
   */
  link: 'direct object'
  /**
   * An array of strings, which will be displayed on the node.
   * @type string[]
   * @optional
   */
  attributes: [ 'action', ... ]
  /**
   * An array of spans, where each span represents a series of characters in the `text` property (
   * of the Tree) that should be highlighted when the node is hovered.
   * @type object[]
   * @optional
   */
  spans: [ Span { ... }, ... ]
  /**
   * An array containing the children of the node.
   * @type object[]
   * @optional
   */
  children: [ Node, ... ]

Each span refers to a sequence of characters in the original sentence (the text property of the Tree) that should be highlighted when the node and is hovered. Each span should have the following properties:

Span
  /**
   * The index indicating where the span begins.
   * @type number
   * @required
   */
  start
  /**
   * The index (exclusive) where the span ends.
   * @type number
   * @required
   */
  end
  /**
   * An optional identifier indicating the type of span. As of now, the only value you'll likely
   * put here is "ignored", which indicates that the span shouldn't be emphasized when the node
   * is hovered.
   * @type string
   * @optional
   */
  spanType

You can see a full example of a tree here.

Style Maps

The Hierplane data format supports three optional style maps (objects containing a set of key-value pairs) that can be added to a Tree object:

  • nodeTypeToStyle applies specified styles to nodes with particular nodeType values.
  • linkToPosition tells the app how to position nodes with particular link values.
  • linkNameToLabel translates particular link values into custom display labels.

nodeTypeToStyle

A nodeTypeToStyle mapping applies specified styles to nodes with particular nodeType values. In the following example, any node with a nodeType value of "verb" will have "color1" and "strong" styles applied. This gets rendered as CSS modifier classes.

"nodeTypeToStyle": {
  "verb": ["color1", "strong"],
  "noun": ["color2"],
  "modifier": ["color3"],
  "sequence": ["seq"],
  "reference": ["placeholder"]
}

Note: Hierplane will automatically color-code nodes based on their nodeType values, so out-of-the-box, you do not need to worry about nodeTypeToStyle mapping. However, as soon as you add this map and introduce a custom style on any nodeType, you will need to manually apply all node styles, as the automatic styling will be disabled at that point.

Supported nodeTypeToStyle Keys:

Any potential nodeType value is a valid key, whether it's being used in the current tree or not.

Supported nodeTypeToStyle Values:

Valid values are arrays of strings. While you are free to apply any string as a style, only the following strings are supported by the built-in stylesheet:

  • "color0" colors node gray.
  • "color1" colors node green.
  • "color2" colors node blue.
  • "color3" colors node pink.
  • "color4" colors node yellow.
  • "color5" colors node purple.
  • "color6" colors node aqua.
  • "strong" makes node text larger and bold.
  • "seq" renders node as a sequence container. Note that this style is required to correctly render nodes that have at least one child node with a nodeType value of "inside". Also note that a node with a "seq" style will have its default node text hidden to make room for its "inside" children.
  • "placeholder" renders node with a transparent background and light dotted outline (to communicate a placeholder status, recommended for certain linguistic concepts such as relative references).

Note: at this time, the only supported colors are the 7 mentioned above.

A linkToPosition mapping tells the app how to position nodes with particular link values. In the following example, any node with a link value of "subj" will be given a position of "left", while nodes with link values of "obj" will be given a position of "right" and so on.

"linkToPosition": {
  "subj": "left",
  "obj": "right",
  "seqChild": "inside"
}

Supported linkToPosition Keys:

Any potential link value is a valid key, whether it's being used in the current tree or not.

Supported linkToPosition Values:

  • inside - Positions node inside of its parent. This was added mainly to support linguistic sequences (e.g. "The land has trees, grass, and animals." where the object of the sentence is a sequence of nouns).

  • left - Positions a node to the left of its parent (well suited for subjects of a sentence).

  • right - Positions a node to the right of its parent (well suited for objects of a sentence).

  • down - Positions a node directly underneath its parent (we call this layout "canonical"). All nodes have a position of down by default, so it is not necessary to explicitly set this.

A linkNameToLabel mapping translates particular link values into custom display labels. In the following example, any node with a link value of "subj" will be displayed as "S". This is especially useful for nodes positioned "left" and "right", as those configurations lose aesthetic value with long link labels.

"linkNameToLabel": {
  "subj": "S",
  "obj": "O"
}

Supported linkNameToLabel Keys:

Any potential link value is a valid key, whether it's being used in the current tree or not.

Supported linkNameToLabel Values:

Any string is a valid value.

Contributing

To run the code locally and verify your changes, follow these steps:

  1. Clone the repository.
$ git clone [email protected]:allenai/hierplane.git
  1. Install nodejs. This was built against version v6.11.5. You're free to try something more recent.

  2. Install the dependencies:

$ cd hierplane/
$ npm install
  1. Run the watch target:
$ npm start
  1. Open http://localhost:3000 in your browser of choice.

If you want to change the port on which the webserver is bound, set the HIERPLANE_DEV_SERVER_PORT environment variable to one of your choosing.

Publishing

In order to publish, you will need to be a collaborator on the Hierplane NPM project.

  1. Make sure to increment the Hierplane version in package.json.
  2. If you're not already logged in, from your hierplane project folder, enter npm login and log in with your NPM credentials.
  3. Execute node bin/publish.js.

hierplane's People

Contributors

aaronsarnat avatar aimichal avatar codeviking avatar jonborchardt avatar pixelday avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hierplane's Issues

Hierplane can't render a tree where the root node doesn't have any children.

It fails with this exception:

index.js:2177 TypeError: Reduce of empty array with no initial value
    at Array.reduce (<anonymous>)
    at getAllChildSpans (helpers.js:249)
    at getSpanBoundaries (helpers.js:222)
    at translateSpans (helpers.js:168)
    at Tree.fetchInitialParse (Tree.js:333)
    at Tree.handleEmpty (Tree.js:199)
    at Tree.componentDidMount (Tree.js:177)
    at ReactCompositeComponent.js:262
    at measureLifeCyclePerf (ReactCompositeComponent.js:73)
    at ReactCompositeComponent.js:261
    at CallbackQueue.notifyAll (CallbackQueue.js:74)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:78)
    at ReactReconcileTransaction.closeAll (Transaction.js:207)
    at ReactReconcileTransaction.perform (Transaction.js:154)
    at ReactUpdatesFlushTransaction.perform (Transaction.js:141)
    at ReactUpdatesFlushTransaction.perform (ReactUpdates.js:87)
    at Object.flushBatchedUpdates (ReactUpdates.js:170)
    at ReactDefaultBatchingStrategyTransaction.closeAll (Transaction.js:207)
    at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:154)
    at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:60)
    at Object.enqueueUpdate (ReactUpdates.js:198)
    at enqueueUpdate (ReactUpdateQueue.js:22)
    at Object.enqueueSetState (ReactUpdateQueue.js:216)
    at Demo../node_modules/react/lib/ReactBaseClasses.js.ReactComponent.setState (ReactBaseClasses.js:62)
    at App.js:58
    at listener (createTransitionManager.js:54)
    at createTransitionManager.js:73
    at Array.forEach (<anonymous>)
    at Object.notifyListeners (createTransitionManager.js:72)
    at setState (createBrowserHistory.js:95)
    at createBrowserHistory.js:186
    at Object.confirmTransitionTo (createTransitionManager.js:44)
    at Object.push (createBrowserHistory.js:166)
    at SrlComponent.js:367
    at <anonymous>

When given a tree that has no children, i.e.:

root : {
   children: [],
   word: "were"
},
text: ".... were awesome"

Ideally it shouldn't crash in this case.

Revisit how nodeType color mapping is auto-generated

Currently, automatic nodeType styling (e.g. color1, color2, etc.) is incremented by the order that distinct nodeType values are found in the data. One drawback to this approach is that root and first-level children will not always be the same colors. This can be somewhat disorienting when visualizing multiple structures.

Make passage optional

Passage makes sense for sentence diagramming, but not so much with other kinds of hierarchical structures that aren't related to linguistics (e.g. taxonomy of organisms).

Chrome - Disembodied Children

This just started happening in Chrome only. Parent nodes are not vertically expanding to be as big as their children.

Hierplane website, running the latest build of Hierplane:

image

Euclid demo running a several-week(month?)-old version:

image


Steps to reproduce:

  1. Go to https://allenai.github.io/hierplane/

  2. Click "Expand all nodes" in upper right of Hierplane container
    image

  3. Note what looks like floating nodes


My suspicion is that Chrome released an update to its CSS-rendering engine that handles the flex rules slightly differently for this edge case.

Consider making effects optional

Perhaps we should make drop shadows, text shadows, gradients, and transitions optional (but turned on by default) to improve rendering performance.

Make minimum collapsable depth user-defined

Current (hard-coded) default is depth of 1 (immediate children of root), as this was the desired functionality for Euclid. However, this may not be ideal for other applications (e.g. AllenNLP SRL demo) which would benefit from a minimum collapsable depth of 0.

Revisit use of external font

Issue based on Hierplane MVP website PR feedback: #50 (review)

Main pros for removing custom font: performance

Main pros for keeping custom font: aesthetics, consistency

The decision was made to leave custom fonts in place for the time being, with the understanding that we'd take another look at this issue at some point in the future.

Remove Jekyll generated folders from .gitignore on master

Right now we have 2 generated folders included in Hierplane's .gitignore file:

.sass-cache
_site

These are only relevant to the gh-pages branch, but were added for convenience since they would persist as untracked files when switching between gh-pages branch and master.

However, it is undesirable to have something in the Hierplane codebase that is not relevant (public website is a separate entity, even though it happens to share a repo as of this writing), so those lines should eventually be removed.


Related: Ignore Jekyll generated folders #49

Getting React and Redux production build warnings when using CDN-hosted JS bundle

Currently getting these warnings on Hierplane website that points to new bundle at <script src="//unpkg.com/hierplane/dist/static/hierplane.min.js"></script>

image

hierplane.min.js:1 You are currently using minified code outside of NODE_ENV === 'production'. This means that you are running a slower development build of Redux. You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) to ensure you have the correct code for your production build.
n.default @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.243../applyMiddleware @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.81../wrapMapToProps @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.80.../components/connectAdvanced @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.87../components/Provider @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.18.../stores/modules/ui @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.4../EmptyTree.js @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.10../IconSprite.js @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.13../Tree.js @ hierplane.min.js:1
r @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
o.33.../module/index.js @ hierplane.min.js:1
r @ hierplane.min.js:1
e @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
(anonymous) @ hierplane.min.js:1
hierplane.min.js:1 Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster. See https://fb.me/react-minification for more details.

Replace `node.word` with `node.text.

Each node has a word property, which for flexibility / clarity should just be named text (this makes the library more approachable by people not using it in the NLP domain).

Build Examples page on Hierplane website

This page and the nav links / CTA buttons that point to it were omitted from the MVP soft-launch of https://allenai.github.io/hierplane/

TODO

  1. Create custom JSONs of different example trees (could add these to core as well)
  2. Build UI for example selection inside Demo page
  3. Enable links that point to it
  4. Extra credit: build a mobile-friendly use case

Design

image

Revisit `height: 0` fix for table cells allowing their children to inherit their height

The fix (Fixing chrome table cell content height bug #76) for the Chrome - Disembodied Children #75 issue left us with an undesirable, somewhat hacky solution:

height: 0; // TODO(aarons): see if this hack can be removed if/when Chrome addresses their table cell content height bug

As of this writing, it works cross-browser, but would be better if there were a more elegant way to handle this if possible. It would also be useful to determine, unquestionably, that this is indeed the result of a Chromium bug (something they may fix) or if it is intentional (closer to W3C spec).

Firefox breakage - height: 0

image

Just discovered that the height: 0 hack that fixed Chrome - Disembodied Children #75 is now causing an even worse bug in Firefox. Confirmed that removing this style fixes Firefox but re-introduces the disembodied children bug in Chrome.

Consider a Firefox-specific selector hack for disabling height: 0 as a bandaid fix until a more thorough analysis can be done.

Error text font size is off

This is a known issue relating to a heading tag whose parent has a font-size set in ems, but is itself inheriting default font size from browser (hence looking bigger than it should). Easy fix.

image

Sometimes the unpkg.com CDN-hosted resources do not resolve

I've seen this a couple of times on my machine and it's been reported that @DeNeutoy and @codeviking have seen it, too. Sometimes the CDN-hosted resources will become unavailable for a few minutes and then will become available again.

It seems that either the CSS resource or the JS resource can go offline intermittently. I don't think I've yet seen them both go offline at the same time, but I suppose it's possible.

I don't remember exactly what the error messages look like when I tried to navigate to the unresponsive hosted URIs directly (luckily Hierplane works most of the time), but it was something along the lines of "URI... resource not found".

Steps to reproduce unknown.


When the hosted JS disappears, it looks like a big gray empty box and the rest of the JS on the page breaks.

When the hosted CSS disappears, it looks like this:

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.