Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

displacy

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

displacy - npm Package Compare versions

Comparing version 1.0.4 to 1.1.0

372

displacy.js

@@ -5,125 +5,144 @@ //- ----------------------------------

'use strict';
'use strict'
class displaCy {
constructor (api, options) {
this.api = api;
this.container = document.querySelector(options.container || '#displacy');
constructor(api, options) {
this.api = api
this.container =
typeof options.container == 'string'
? document.querySelector(options.container || '#displacy')
: options.container
this.format = options.format || 'spacy';
this.defaultText = options.defaultText || 'Hello World.';
this.defaultModel = options.defaultModel || 'en';
this.collapsePunct = (options.collapsePunct != undefined) ? options.collapsePunct : true;
this.collapsePhrase = (options.collapsePhrase != undefined) ? options.collapsePhrase : true;
this.format = options.format || 'spacy'
this.defaultText = options.defaultText || 'Hello World.'
this.defaultModel = options.defaultModel || 'en'
this.collapsePunct = options.collapsePunct != undefined ? options.collapsePunct : true
this.collapsePhrase = options.collapsePhrase != undefined ? options.collapsePhrase : true
this.onStart = options.onStart || false;
this.onSuccess = options.onSuccess || false;
this.onError = options.onError || false;
this.onStart = options.onStart || false
this.onSuccess = options.onSuccess || false
this.onError = options.onError || false
this.distance = options.distance || 200;
this.offsetX = options.offsetX || 50;
this.arrowSpacing = options.arrowSpacing || 20;
this.arrowWidth = options.arrowWidth || 10;
this.arrowStroke = options.arrowStroke || 2;
this.wordSpacing = options.wordSpacing || 75;
this.font = options.font || 'inherit';
this.color = options.color || '#000000';
this.bg = options.bg || '#ffffff';
this.distance = options.distance || 200
this.offsetX = options.offsetX || 50
this.arrowSpacing = options.arrowSpacing || 20
this.arrowWidth = options.arrowWidth || 10
this.arrowStroke = options.arrowStroke || 2
this.wordSpacing = options.wordSpacing || 75
this.font = options.font || 'inherit'
this.color = options.color || '#000000'
this.bg = options.bg || '#ffffff'
}
parse(text = this.defaultText, model = this.defaultModel, settings = {}) {
if(typeof this.onStart === 'function') this.onStart();
if (typeof this.onStart === 'function') this.onStart()
let xhr = new XMLHttpRequest();
xhr.open('POST', this.api, true);
xhr.setRequestHeader('Content-type', 'text/plain');
let xhr = new XMLHttpRequest()
xhr.open('POST', this.api, true)
xhr.setRequestHeader('Content-type', 'text/plain')
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200) {
if(typeof this.onSuccess === 'function') this.onSuccess();
this.render(JSON.parse(xhr.responseText), settings, text);
if (xhr.readyState === 4 && xhr.status === 200) {
if (typeof this.onSuccess === 'function') this.onSuccess()
this.render(JSON.parse(xhr.responseText), settings, text)
} else if (xhr.status !== 200) {
if (typeof this.onError === 'function') this.onError(xhr.statusText)
}
else if(xhr.status !== 200) {
if(typeof this.onError === 'function') this.onError(xhr.statusText);
}
}
xhr.onerror = () => {
xhr.abort();
if(typeof this.onError === 'function') this.onError();
xhr.abort()
if (typeof this.onError === 'function') this.onError()
}
xhr.send(JSON.stringify({ text, model,
collapse_punctuation: (settings.collapsePunct != undefined) ? settings.collapsePunct : this.collapsePunct,
collapse_phrases: (settings.collapsePhrase != undefined) ? settings.collapsePhrase : this.collapsePhrase
}));
xhr.send(
JSON.stringify({
text,
model,
collapse_punctuation:
settings.collapsePunct != undefined
? settings.collapsePunct
: this.collapsePunct,
collapse_phrases:
settings.collapsePhrase != undefined
? settings.collapsePhrase
: this.collapsePhrase
})
)
}
render(parse, settings = {}, text) {
parse = this.handleConversion(parse);
parse = this.handleConversion(parse)
if(text) console.log(`%c💥 JSON for "${text}"\n%c${JSON.stringify(parse)}`, 'font: bold 16px/2 arial, sans-serif', 'font: 13px/1.5 Consolas, "Andale Mono", Menlo, Monaco, Courier, monospace');
if (text)
console.log(
`%c💥 JSON for "${text}"\n%c${JSON.stringify(parse)}`,
'font: bold 16px/2 arial, sans-serif',
'font: 13px/1.5 Consolas, "Andale Mono", Menlo, Monaco, Courier, monospace'
)
this.levels = [...new Set(parse.arcs.map(({ end, start }) => end - start).sort((a, b) => a - b))];
this.highestLevel = this.levels.indexOf(this.levels.slice(-1)[0]) + 1;
this.offsetY = this.distance / 2 * this.highestLevel;
this.levels = [
...new Set(parse.arcs.map(({ end, start }) => end - start).sort((a, b) => a - b))
]
this.highestLevel = this.levels.indexOf(this.levels.slice(-1)[0]) + 1
this.offsetY = (this.distance / 2) * this.highestLevel
const width = this.offsetX + parse.words.length * this.distance;
const height = this.offsetY + 3 * this.wordSpacing;
const width = this.offsetX + parse.words.length * this.distance
const height = this.offsetY + 3 * this.wordSpacing
this.container.innerHTML = '';
this.container.appendChild(this._el('svg', {
id: 'displacy-svg',
classnames: [ 'displacy' ],
attributes: [
[ 'width', width ],
[ 'height', height ],
[ 'viewBox', `0 0 ${width} ${height}`],
[ 'preserveAspectRatio', 'xMinYMax meet' ],
[ 'data-format', this.format ]
],
style: [
[ 'color', settings.color || this.color ],
[ 'background', settings.bg || this.bg ],
[ 'fontFamily', settings.font || this.font ]
],
children: [
...this.renderWords(parse.words),
...this.renderArrows(parse.arcs)
]
}));
this.container.innerHTML = ''
this.container.appendChild(
this._el('svg', {
id: 'displacy-svg',
classnames: ['displacy'],
attributes: [
['width', width],
['height', height],
['viewBox', `0 0 ${width} ${height}`],
['preserveAspectRatio', 'xMinYMax meet'],
['data-format', this.format]
],
style: [
['color', settings.color || this.color],
['background', settings.bg || this.bg],
['fontFamily', settings.font || this.font]
],
children: [...this.renderWords(parse.words), ...this.renderArrows(parse.arcs)]
})
)
}
renderWords(words) {
return (words.map(( { text, tag, data = [] }, i) => this._el('text', {
classnames: [ 'displacy-token' ],
attributes: [
['fill', 'currentColor'],
['data-tag', tag],
['text-anchor', 'middle'],
['y', this.offsetY + this.wordSpacing],
...data.map(([attr, value]) => (['data-' + attr.replace(' ', '-'), value]))
],
children: [
this._el('tspan', {
classnames: [ 'displacy-word' ],
attributes: [
['x', this.offsetX + i * this.distance],
['fill', 'currentColor'],
['data-tag', tag]
],
text: text
}),
this._el('tspan', {
classnames: [ 'displacy-tag' ],
attributes: [
['x', this.offsetX + i * this.distance],
['dy', '2em'],
['fill', 'currentColor'],
['data-tag', tag]
],
text: tag
})
]
})));
return words.map(({ text, tag, data = [] }, i) =>
this._el('text', {
classnames: ['displacy-token'],
attributes: [
['fill', 'currentColor'],
['data-tag', tag],
['text-anchor', 'middle'],
['y', this.offsetY + this.wordSpacing],
...data.map(([attr, value]) => ['data-' + attr.replace(' ', '-'), value])
],
children: [
this._el('tspan', {
classnames: ['displacy-word'],
attributes: [
['x', this.offsetX + i * this.distance],
['fill', 'currentColor'],
['data-tag', tag]
],
text: text
}),
this._el('tspan', {
classnames: ['displacy-tag'],
attributes: [
['x', this.offsetX + i * this.distance],
['dy', '2em'],
['fill', 'currentColor'],
['data-tag', tag]
],
text: tag
})
]
})
)
}

@@ -133,28 +152,41 @@

return arcs.map(({ label, end, start, dir, data = [] }, i) => {
const level = this.levels.indexOf(end - start) + 1;
const startX = this.offsetX + start * this.distance + this.arrowSpacing * (this.highestLevel - level) / 4;
const startY = this.offsetY;
const endpoint = this.offsetX + (end - start) * this.distance + start * this.distance - this.arrowSpacing * (this.highestLevel - level) / 4;
const rand = Math.random()
.toString(36)
.substr(2, 8)
const level = this.levels.indexOf(end - start) + 1
const startX =
this.offsetX +
start * this.distance +
(this.arrowSpacing * (this.highestLevel - level)) / 4
const startY = this.offsetY
const endpoint =
this.offsetX +
(end - start) * this.distance +
start * this.distance -
(this.arrowSpacing * (this.highestLevel - level)) / 4
let curve = this.offsetY - level * this.distance / 2;
if(curve == 0 && this.levels.length > 5) curve = -this.distance;
let curve = this.offsetY - (level * this.distance) / 2
if (curve == 0 && this.levels.length > 5) curve = -this.distance
return this._el('g', {
classnames: [ 'displacy-arrow' ],
classnames: ['displacy-arrow'],
attributes: [
[ 'data-dir', dir ],
[ 'data-label', label ],
...data.map(([attr, value]) => (['data-' + attr.replace(' ', '-'), value]))
['data-dir', dir],
['data-label', label],
...data.map(([attr, value]) => ['data-' + attr.replace(' ', '-'), value])
],
children: [
children: [
this._el('path', {
id: 'arrow-' + i,
classnames: [ 'displacy-arc' ],
id: 'arrow-' + rand,
classnames: ['displacy-arc'],
attributes: [
[ 'd', `M${startX},${startY} C${startX},${curve} ${endpoint},${curve} ${endpoint},${startY}`],
[ 'stroke-width', this.arrowStroke + 'px' ],
[ 'fill', 'none' ],
[ 'stroke', 'currentColor' ],
[ 'data-dir', dir ],
[ 'data-label', label ]
[
'd',
`M${startX},${startY} C${startX},${curve} ${endpoint},${curve} ${endpoint},${startY}`
],
['stroke-width', this.arrowStroke + 'px'],
['fill', 'none'],
['stroke', 'currentColor'],
['data-dir', dir],
['data-label', label]
]

@@ -164,15 +196,13 @@ }),

this._el('text', {
attributes: [
[ 'dy', '1em' ]
],
attributes: [['dy', '1em']],
children: [
this._el('textPath', {
xlink: '#arrow-' + i,
classnames: [ 'displacy-label' ],
xlink: '#arrow-' + rand,
classnames: ['displacy-label'],
attributes: [
[ 'startOffset', '50%' ],
[ 'fill', 'currentColor' ],
[ 'text-anchor', 'middle' ],
[ 'data-label', label ],
[ 'data-dir', dir ]
['startOffset', '50%'],
['fill', 'currentColor'],
['text-anchor', 'middle'],
['data-label', label],
['data-dir', dir]
],

@@ -185,23 +215,53 @@ text: label

this._el('path', {
classnames: [ 'displacy-arrowhead' ],
classnames: ['displacy-arrowhead'],
attributes: [
[ 'd', `M${(dir == 'left') ? startX : endpoint},${startY + 2} L${(dir == 'left') ? startX - this.arrowWidth + 2 : endpoint + this.arrowWidth - 2},${startY - this.arrowWidth} ${(dir == 'left') ? startX + this.arrowWidth - 2 : endpoint - this.arrowWidth + 2},${startY - this.arrowWidth}` ],
[ 'fill', 'currentColor' ],
[ 'data-label', label ],
[ 'data-dir', dir ]
[
'd',
`M${dir == 'left' ? startX : endpoint},${startY + 2} L${
dir == 'left'
? startX - this.arrowWidth + 2
: endpoint + this.arrowWidth - 2
},${startY - this.arrowWidth} ${
dir == 'left'
? startX + this.arrowWidth - 2
: endpoint - this.arrowWidth + 2
},${startY - this.arrowWidth}`
],
['fill', 'currentColor'],
['data-label', label],
['data-dir', dir]
]
})
]
});
});
})
})
}
handleConversion(parse) {
switch(this.format) {
case 'spacy': return parse; break;
case 'google': return({
words: parse.map(({ text: { content: text }, partOfSpeech: { tag }} ) => ({ text, tag })),
arcs: parse.map(({ dependencyEdge: { label, headTokenIndex: j }}, i) => (i != j) ? ({ label, start: Math.min(i, j), end: Math.max(i, j), dir: (j > i) ? 'left' : 'right' }) : null).filter(word => word != null)
}); break;
default: return parse;
switch (this.format) {
case 'spacy':
return parse
break
case 'google':
return {
words: parse.map(({ text: { content: text }, partOfSpeech: { tag } }) => ({
text,
tag
})),
arcs: parse
.map(({ dependencyEdge: { label, headTokenIndex: j } }, i) =>
i != j
? {
label,
start: Math.min(i, j),
end: Math.max(i, j),
dir: j > i ? 'left' : 'right'
}
: null
)
.filter(word => word != null)
}
break
default:
return parse
}

@@ -211,16 +271,24 @@ }

_el(tag, options) {
const { classnames = [], attributes = [], style = [], children = [], text, id, xlink } = options;
const ns = 'http://www.w3.org/2000/svg';
const nsx = 'http://www.w3.org/1999/xlink';
const el = document.createElementNS(ns, tag);
const {
classnames = [],
attributes = [],
style = [],
children = [],
text,
id,
xlink
} = options
const ns = 'http://www.w3.org/2000/svg'
const nsx = 'http://www.w3.org/1999/xlink'
const el = document.createElementNS(ns, tag)
classnames.forEach(name => el.classList.add(name));
attributes.forEach(([attr, value]) => el.setAttribute(attr, value));
style.forEach(([ prop, value ]) => el.style[prop] = value);
if(xlink) el.setAttributeNS(nsx, 'xlink:href', xlink);
if(text) el.appendChild(document.createTextNode(text));
if(id) el.id = id;
children.forEach(child => el.appendChild(child));
return el;
classnames.forEach(name => el.classList.add(name))
attributes.forEach(([attr, value]) => el.setAttribute(attr, value))
style.forEach(([prop, value]) => (el.style[prop] = value))
if (xlink) el.setAttributeNS(nsx, 'xlink:href', xlink)
if (text) el.appendChild(document.createTextNode(text))
if (id) el.id = id
children.forEach(child => el.appendChild(child))
return el
}
}
{
"name": "displacy",
"version": "1.0.4",
"description": "An open-source NLP visualiser for the modern web",
"main": "displacy.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/explosion/displacy.git"
},
"keywords": [
"nlp",
"visualizer",
"spacy"
],
"author": "Ines Montani",
"license": "MIT",
"bugs": {
"url": "https://github.com/explosion/displacy/issues"
},
"homepage": "https://github.com/explosion/displacy#readme"
"name": "displacy",
"version": "1.1.0",
"description": "An open-source NLP visualiser for the modern web",
"main": "displacy.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/explosion/displacy.git"
},
"keywords": [
"nlp",
"visualizer",
"spacy"
],
"author": "Ines Montani",
"license": "MIT",
"bugs": {
"url": "https://github.com/explosion/displacy/issues"
},
"homepage": "https://github.com/explosion/displacy#readme"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc