Spaces:
Running
Running
Julien Chaumond
commited on
Commit
·
44360bd
1
Parent(s):
e4685f5
Checkpoint 5
Browse files- js-src/SvgArrow.ts +82 -0
- js-src/coref.ts +36 -3
- less/style.less +29 -2
js-src/SvgArrow.ts
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
class SvgArrow {
|
4 |
+
static yArrows: number = 0;
|
5 |
+
|
6 |
+
container: HTMLElement;
|
7 |
+
markFrom: HTMLElement;
|
8 |
+
markTo: HTMLElement;
|
9 |
+
score: number;
|
10 |
+
classNames: string[] = [];
|
11 |
+
constructor(container: HTMLElement, markFrom: HTMLElement, markTo: HTMLElement, score: number) {
|
12 |
+
this.container = container;
|
13 |
+
this.markFrom = markFrom;
|
14 |
+
this.markTo = markTo;
|
15 |
+
this.score = score;
|
16 |
+
}
|
17 |
+
|
18 |
+
/// From displacy.js
|
19 |
+
_el(tag, options): SVGElement {
|
20 |
+
const { classnames = [], attributes = [], style = [], children = [], text, id, xlink } = options;
|
21 |
+
const ns = 'http://www.w3.org/2000/svg';
|
22 |
+
const nsx = 'http://www.w3.org/1999/xlink';
|
23 |
+
const el = document.createElementNS(ns, tag);
|
24 |
+
|
25 |
+
classnames.forEach(name => el.classList.add(name));
|
26 |
+
attributes.forEach(([attr, value]) => el.setAttribute(attr, value));
|
27 |
+
style.forEach(([ prop, value ]) => el.style[prop] = value);
|
28 |
+
if(xlink) el.setAttributeNS(nsx, 'xlink:href', xlink);
|
29 |
+
if(text) el.appendChild(document.createTextNode(text));
|
30 |
+
if(id) el.id = id;
|
31 |
+
children.forEach(child => el.appendChild(child));
|
32 |
+
return el;
|
33 |
+
}
|
34 |
+
|
35 |
+
|
36 |
+
generate(): SVGElement {
|
37 |
+
const rand = Math.random().toString(36).substr(2, 8);
|
38 |
+
|
39 |
+
const startX = this.markTo.getBoundingClientRect().left
|
40 |
+
- this.container.getBoundingClientRect().left
|
41 |
+
+ this.markTo.getBoundingClientRect().width / 2;
|
42 |
+
|
43 |
+
const endX = this.markFrom.getBoundingClientRect().left
|
44 |
+
- this.container.getBoundingClientRect().left
|
45 |
+
+ this.markFrom.getBoundingClientRect().width / 2;
|
46 |
+
|
47 |
+
const curveY = Math.max(-50, SvgArrow.yArrows - (endX - startX) / 3.2);
|
48 |
+
|
49 |
+
return this._el('g', {
|
50 |
+
classnames: [ 'displacy-arrow' ].concat(this.classNames),
|
51 |
+
children: [
|
52 |
+
this._el('path', {
|
53 |
+
id: `arrow-${rand}`,
|
54 |
+
classnames: [ 'displacy-arc' ],
|
55 |
+
attributes: [
|
56 |
+
[ 'd', `M${startX},${SvgArrow.yArrows} C${startX},${curveY} ${endX},${curveY} ${endX},${SvgArrow.yArrows}`],
|
57 |
+
[ 'stroke-width', '2px' ],
|
58 |
+
[ 'fill', 'none' ],
|
59 |
+
[ 'stroke', 'currentColor' ],
|
60 |
+
]
|
61 |
+
}),
|
62 |
+
this._el('text', {
|
63 |
+
attributes: [
|
64 |
+
[ 'dy', '1em' ]
|
65 |
+
],
|
66 |
+
children: [
|
67 |
+
this._el('textPath', {
|
68 |
+
xlink: `#arrow-${rand}`,
|
69 |
+
classnames: [ 'displacy-label' ],
|
70 |
+
attributes: [
|
71 |
+
[ 'startOffset', '50%' ],
|
72 |
+
[ 'fill', 'currentColor' ],
|
73 |
+
[ 'text-anchor', 'middle' ],
|
74 |
+
],
|
75 |
+
text: this.score.toFixed(2)
|
76 |
+
})
|
77 |
+
]
|
78 |
+
}),
|
79 |
+
]
|
80 |
+
});
|
81 |
+
}
|
82 |
+
}
|
js-src/coref.ts
CHANGED
@@ -82,9 +82,42 @@ class Coref {
|
|
82 |
|
83 |
this.container.innerHTML = `<div class="text">${markup}</div>`;
|
84 |
/// SVG
|
|
|
85 |
this.svgResize();
|
86 |
-
|
87 |
-
window.
|
88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
}
|
|
|
82 |
|
83 |
this.container.innerHTML = `<div class="text">${markup}</div>`;
|
84 |
/// SVG
|
85 |
+
this.svgContainer.textContent = ""; // Empty
|
86 |
this.svgResize();
|
87 |
+
(<any>window).container = this.container;
|
88 |
+
(<any>window).svgContainer = this.svgContainer;
|
89 |
+
/**
|
90 |
+
* Arrows preparation
|
91 |
+
*/
|
92 |
+
const endY = document.querySelector('.container .text')!.getBoundingClientRect().top
|
93 |
+
- this.container.getBoundingClientRect().top
|
94 |
+
- 2;
|
95 |
+
SvgArrow.yArrows = endY;
|
96 |
+
/**
|
97 |
+
* Render arrows
|
98 |
+
*/
|
99 |
+
for (const [__from, scores] of Object.entries(res.pairScores)) {
|
100 |
+
const from = parseInt(__from, 10); /// Convert all string keys to ints...
|
101 |
+
for (const [__to, score] of Object.entries(scores)) {
|
102 |
+
const to = parseInt(__to, 10);
|
103 |
+
|
104 |
+
// Positions:
|
105 |
+
const markFrom = document.querySelector(`mark[data-index="${from}"]`) as HTMLElement;
|
106 |
+
const markTo = document.querySelector(`mark[data-index="${to}"]`) as HTMLElement;
|
107 |
+
// console.log(markFrom, markTo, score); // todo remove
|
108 |
+
const arrow = new SvgArrow(this.container, markFrom, markTo, score);
|
109 |
+
// Is this a resolved coref?
|
110 |
+
if (score >= Math.max(...Object.values(scores))) {
|
111 |
+
arrow.classNames.push('score-ok'); // Best pairwise score
|
112 |
+
// Is it the better than the singleScore?
|
113 |
+
const singleScore = res.singleScores[from];
|
114 |
+
if (singleScore && score >= singleScore) {
|
115 |
+
arrow.classNames.push('score-best');
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
this.svgContainer.appendChild(arrow.generate());
|
120 |
+
}
|
121 |
+
}
|
122 |
}
|
123 |
}
|
less/style.less
CHANGED
@@ -92,7 +92,7 @@ code, pre {
|
|
92 |
.container {
|
93 |
font-size: 20px;
|
94 |
white-space: nowrap;
|
95 |
-
padding:
|
96 |
mark {
|
97 |
position: relative;
|
98 |
span.single-score {
|
@@ -122,7 +122,34 @@ body.debug {
|
|
122 |
position: absolute;
|
123 |
top: 0; left: 0; right: 0; bottom: 0;
|
124 |
z-index: -1;
|
125 |
-
background-color: pink;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
}
|
127 |
|
128 |
/**
|
|
|
92 |
.container {
|
93 |
font-size: 20px;
|
94 |
white-space: nowrap;
|
95 |
+
padding: 300px 40px 200px 40px; /// Keep a large-ish bottom padding b/c we use it to scroll the whole container.
|
96 |
mark {
|
97 |
position: relative;
|
98 |
span.single-score {
|
|
|
122 |
position: absolute;
|
123 |
top: 0; left: 0; right: 0; bottom: 0;
|
124 |
z-index: -1;
|
125 |
+
// background-color: pink;
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Arrows
|
131 |
+
*/
|
132 |
+
|
133 |
+
.displacy-arrow {
|
134 |
+
color: #cad2cd; // #87908a;
|
135 |
+
visibility: hidden;
|
136 |
+
.displacy-label {
|
137 |
+
font-family: @fontMonospace;
|
138 |
+
font-size: 12px;
|
139 |
+
}
|
140 |
+
&.score-ok {
|
141 |
+
color: #ff9378;
|
142 |
+
}
|
143 |
+
&.score-best {
|
144 |
+
color: #ff211d;
|
145 |
+
visibility: visible;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
body.debug {
|
150 |
+
.displacy-arrow {
|
151 |
+
visibility: visible !important;
|
152 |
+
}
|
153 |
}
|
154 |
|
155 |
/**
|