Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Dominik Schwabe
comparefile
Commits
c5c669a7
Commit
c5c669a7
authored
Jun 22, 2021
by
Dominik Schwabe
Browse files
added markup scroll on click
parent
45b5b97a
Changes
3
Hide whitespace changes
Inline
Side-by-side
frontend/src/components/Summarize.js
View file @
c5c669a7
...
...
@@ -11,7 +11,7 @@ import { Badge } from "./utils/Badge";
import
{
Button
}
from
"
./utils/Button
"
;
import
{
Bars
,
EyeClosed
,
EyeOpen
,
ThumbsDown
,
ThumbsUp
}
from
"
./utils/Icons
"
;
import
{
CenterLoading
}
from
"
./utils/Loading
"
;
import
{
Markup
}
from
"
./utils/Markup
"
;
import
{
Markup
,
useMarkupScroll
}
from
"
./utils/Markup
"
;
const
Feedback
=
({
summary
})
=>
{
const
{
name
,
summaryText
,
originalText
,
url
}
=
summary
;
...
...
@@ -215,7 +215,7 @@ const generateStatistics = (text, summaryMarkup) => {
};
};
const
Summary
=
({
markup
,
summary
,
markupState
,
showMarkup
})
=>
{
const
Summary
=
({
markup
,
summary
,
markupState
,
scrollState
,
showMarkup
})
=>
{
const
{
originalText
,
summaryText
}
=
summary
;
const
{
numWords
,
percentOverlap
}
=
generateStatistics
(
originalText
,
markup
[
1
]);
...
...
@@ -225,7 +225,7 @@ const Summary = ({ markup, summary, markupState, showMarkup }) => {
<
Badge
>
{
`
${
numWords
}
words`
}
<
/Badge
>
<
Badge
>
{
`
${(
percentOverlap
*
100
).
toFixed
(
0
)}
% overlap`
}
<
/Badge
>
<
/div
>
<
Markup
markups
=
{
markup
[
1
]}
markupState
=
{
markupState
}
showMarkup
=
{
showMarkup
}
/
>
<
Markup
markups
=
{
markup
[
1
]}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
showMarkup
=
{
showMarkup
}
/
>
<
div
className
=
"
uk-flex uk-flex-right
"
>
<
Feedback
summary
=
{
summary
}
/
>
<
/div
>
...
...
@@ -233,7 +233,7 @@ const Summary = ({ markup, summary, markupState, showMarkup }) => {
);
};
// Processed document
const
Document
=
({
title
,
markup
,
markupState
,
showMarkup
,
clearMarkups
})
=>
(
const
Document
=
({
title
,
markup
,
markupState
,
scrollState
,
showMarkup
,
clearMarkups
})
=>
(
<>
<
div
>
<
h4
style
=
{{
margin
:
"
10px
"
,
marginBottom
:
"
0
"
}}
>
{
title
}
<
/h4
>
...
...
@@ -241,7 +241,7 @@ const Document = ({ title, markup, markupState, showMarkup, clearMarkups }) => (
className
=
"
uk-card uk-card-default uk-card-body
"
style
=
{{
height
:
"
60vh
"
,
width
:
"
auto
"
,
overflow
:
"
auto
"
,
padding
:
"
20px
"
}}
>
<
Markup
markups
=
{
markup
}
markupState
=
{
markupState
}
showMarkup
=
{
showMarkup
}
/
>
<
Markup
markups
=
{
markup
}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
showMarkup
=
{
showMarkup
}
/
>
<
/div
>
<
button
className
=
"
uk-button uk-button-primary uk-margin-top uk-width-1-1
"
...
...
@@ -264,6 +264,7 @@ const SummaryTabView = ({
const
[
summaryIndex
,
setSummaryIndex
]
=
useState
(
0
);
const
{
summarizers
}
=
useContext
(
SummarizersContext
);
const
markupState
=
useState
(
null
);
const
scrollState
=
useMarkupScroll
();
return
(
<
div
className
=
"
uk-flex
"
>
...
...
@@ -276,6 +277,7 @@ const SummaryTabView = ({
title
=
{
title
}
markup
=
{
markups
[
summaryIndex
][
0
]}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
showMarkup
=
{
showOverlap
}
/
>
<
/div
>
...
...
@@ -309,6 +311,7 @@ const SummaryTabView = ({
summary
=
{
summaries
[
index
]}
showMarkup
=
{
showOverlap
}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
/
>
<
/li
>
))}
...
...
frontend/src/components/utils/Markup.js
View file @
c5c669a7
import
React
,
{
useMemo
,
useState
,
memo
}
from
"
react
"
;
import
React
,
{
memo
,
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
"
react
"
;
const
innerHoverStyle
=
{
background
:
"
yellow
"
,
color
:
"
black
"
,
display
:
"
relative
"
};
const
baseMarkupStyle
=
{
padding
:
"
2
px
"
,
borderRadius
:
"
0px
"
};
const
baseMarkupStyle
=
{
padding
:
"
1
px
"
,
borderRadius
:
"
0px
"
};
const
outerHoverStyle
=
{
...
baseMarkupStyle
,
...
innerHoverStyle
};
const
TaggedMarkup
=
({
markup
,
markupState
,
showMarkup
})
=>
{
const
useMarkupScroll
=
()
=>
useState
([
null
,
null
,
null
]);
const
Scroll
=
({
docIndex
,
matchOrder
,
groupSizes
,
tag
,
scrollState
,
allowScroll
,
children
})
=>
{
const
[
scrollMarkup
,
setScrollMarkup
]
=
scrollState
;
const
[
scrollDoc
,
scrollTag
,
scrollOrder
]
=
scrollMarkup
;
const
scrollNext
=
()
=>
{
if
(
allowScroll
&&
scrollTag
===
tag
&&
scrollDoc
===
1
-
docIndex
)
setScrollMarkup
([
scrollDoc
,
scrollTag
,
(
scrollOrder
+
1
)
%
groupSizes
[
scrollDoc
]]);
else
setScrollMarkup
([
1
-
docIndex
,
tag
,
0
]);
};
const
scrollRef
=
useRef
();
useEffect
(()
=>
{
if
(
docIndex
===
scrollMarkup
[
0
]
&&
tag
===
scrollMarkup
[
1
]
&&
matchOrder
===
scrollMarkup
[
2
])
{
scrollRef
.
current
.
scrollIntoView
({
block
:
"
center
"
,
behavior
:
"
smooth
"
,
inline
:
"
start
"
});
}
},
[
scrollMarkup
,
docIndex
,
matchOrder
]);
return
(
<
span
ref
=
{
scrollRef
}
onClick
=
{
scrollNext
}
>
{
children
}
<
/span
>
);
};
const
TaggedMarkup
=
({
markup
,
markupState
,
scrollState
,
allowScroll
,
showMarkup
})
=>
{
let
props
=
{};
let
style
=
{};
const
[
content
,
information
]
=
markup
;
const
[
tag
,
bgcolor
,
fgcolor
]
=
information
const
[
tag
,
bgcolor
,
fgcolor
,
docIndex
,
matchOrder
,
groupSizes
]
=
information
;
if
(
showMarkup
)
style
=
{
...
baseMarkupStyle
,
background
:
bgcolor
,
color
:
fgcolor
};
if
(
markupState
)
{
const
[
currMarkup
,
setCurrMarkup
]
=
markupState
;
...
...
@@ -17,31 +40,77 @@ const TaggedMarkup = ({ markup, markupState, showMarkup }) => {
const
onMouseLeave
=
showMarkup
?
()
=>
setCurrMarkup
(
null
)
:
null
;
props
=
{
onMouseEnter
,
onMouseLeave
};
}
return
(
const
markupContent
=
(
<
span
{...
props
}
style
=
{
style
}
>
<
Markup
markups
=
{
content
}
markupState
=
{
markupState
}
showMarkup
=
{
false
}
/
>
<
MarkupRoot
markups
=
{
content
}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
showMarkup
=
{
false
}
/
>
<
/span
>
);
if
(
scrollState
)
return
(
<
Scroll
tag
=
{
tag
}
docIndex
=
{
docIndex
}
matchOrder
=
{
matchOrder
}
groupSizes
=
{
groupSizes
}
markup
=
{
content
}
scrollState
=
{
scrollState
}
allowScroll
=
{
allowScroll
}
>
{
markupContent
}
<
/Scroll
>
);
return
markupContent
;
};
const
StringContent
=
memo
(({
content
})
=>
{
const
lines
=
content
.
split
(
"
\n
"
)
return
<
span
>
<>
{
lines
[
0
]}
<
/
>
{
lines
.
slice
(
1
).
map
(
line
=>
<><
br
/>
{
line
}
<
/>
)
}
<
/span
>
})
const
StringContent
=
memo
(({
content
})
=>
{
const
lines
=
content
.
split
(
"
\n
"
);
return
(
<
span
>
<>
{
lines
[
0
]}
<
/
>
{
lines
.
slice
(
1
).
map
((
line
)
=>
(
<>
<
br
/>
{
line
}
<
/
>
))}
<
/span
>
);
});
const
Markup
=
({
markups
,
markupState
,
matchState
,
showMarkup
=
true
})
=>
(
const
MarkupRoot
=
({
markups
,
markupState
,
scrollState
,
allowScroll
,
showMarkup
})
=>
{
console
.
log
(
scrollState
)
return
(
<>
{
markups
.
map
((
child
,
i
)
=>
typeof
child
===
"
string
"
?
(
<
StringContent
key
=
{
i
}
content
=
{
child
}
/
>
)
:
(
<
TaggedMarkup
key
=
{
i
}
markup
=
{
child
}
markupState
=
{
markupState
}
showMarkup
=
{
showMarkup
}
matchState
=
{
matchState
}
/
>
<
TaggedMarkup
key
=
{
i
}
markup
=
{
child
}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
allowScroll
=
{
allowScroll
}
showMarkup
=
{
showMarkup
}
/
>
)
)}
<
/
>
)};
const
Markup
=
({
markups
,
markupState
,
scrollState
,
showMarkup
=
true
})
=>
(
<
MarkupRoot
markups
=
{
markups
}
markupState
=
{
markupState
}
scrollState
=
{
scrollState
}
allowScroll
=
{
showMarkup
}
showMarkup
=
{
showMarkup
}
/
>
);
export
{
Markup
};
export
{
Markup
,
useMarkupScroll
};
frontend/src/utils/markup.js
View file @
c5c669a7
...
...
@@ -95,30 +95,39 @@ const combine_documents = (docs) => {
};
const
is_self_similar
=
(
start
,
end
,
document_vector
,
suffix_array
)
=>
{
for
(
let
i
=
start
;
i
<
end
;
i
++
)
if
(
document_vector
[
suffix_array
[
i
]]
!==
document_vector
[
suffix_array
[
i
+
1
]]
)
return
false
return
true
}
for
(
let
i
=
start
;
i
<
end
;
i
++
)
if
(
document_vector
[
suffix_array
[
i
]]
!==
document_vector
[
suffix_array
[
i
+
1
]])
return
false
;
return
true
;
};
const
update_longest_match
=
(
start
,
end
,
match_length
,
longest_match_array
)
=>
{
for
(
let
i
=
start
;
i
<=
end
;
i
++
)
if
(
longest_match_array
[
i
]
<
match_length
)
longest_match_array
[
i
]
=
match_length
}
for
(
let
i
=
start
;
i
<=
end
;
i
++
)
if
(
longest_match_array
[
i
]
<
match_length
)
longest_match_array
[
i
]
=
match_length
;
};
const
is_nested
=
(
start
,
end
,
match_length
,
suffix_array
,
inverse_suffix_array
,
longest_match_array
)
=>
{
const
is_nested
=
(
start
,
end
,
match_length
,
suffix_array
,
inverse_suffix_array
,
longest_match_array
)
=>
{
for
(
let
i
=
start
;
i
<=
end
;
i
++
)
{
if
(
longest_match_array
[
i
]
===
match_length
&&
suffix_array
[
i
]
!==
0
)
{
const
longest_match_before
=
longest_match_array
[
inverse_suffix_array
[
suffix_array
[
i
]
-
1
]];
if
(
longest_match_before
<
match_length
+
1
)
return
false
if
(
longest_match_before
<
match_length
+
1
)
return
false
;
}
}
return
true
}
return
true
;
}
;
const
compute_matches
=
(
docs
,
min_length
,
allow_self_similarities
)
=>
{
const
[
combined_doc
,
document_vector
,
offsets
]
=
combine_documents
(
docs
);
const
suffix_array
=
build_suffix_array
(
combined_doc
);
const
inverse_suffix_array
=
build_inverse_suffix_array
(
suffix_array
);
const
lcp_array
=
build_lcp_array
(
combined_doc
,
suffix_array
,
inverse_suffix_array
);
const
longest_match_array
=
Array
(
lcp_array
.
length
).
fill
(
0
)
const
longest_match_array
=
Array
(
lcp_array
.
length
).
fill
(
0
)
;
lcp_array
.
shift
();
lcp_array
.
push
(
0
);
const
match_groups
=
[];
...
...
@@ -127,7 +136,7 @@ const compute_matches = (docs, min_length, allow_self_similarities) => {
let
curr_start
=
0
;
let
curr_depth
=
0
;
let
i
=
0
let
i
=
0
;
while
(
i
<
lcp_array
.
length
)
{
if
(
lcp_array
[
i
]
>
curr_depth
)
{
start
.
push
(
curr_start
);
...
...
@@ -136,9 +145,12 @@ const compute_matches = (docs, min_length, allow_self_similarities) => {
curr_start
=
i
;
}
else
if
(
lcp_array
[
i
]
<
curr_depth
)
{
if
(
curr_depth
>=
min_length
)
{
if
(
allow_self_similarities
||
!
is_self_similar
(
curr_start
,
i
,
document_vector
,
suffix_array
))
{
if
(
allow_self_similarities
||
!
is_self_similar
(
curr_start
,
i
,
document_vector
,
suffix_array
)
)
{
match_groups
.
push
([
curr_start
,
curr_depth
,
i
]);
update_longest_match
(
curr_start
,
i
,
curr_depth
,
longest_match_array
)
update_longest_match
(
curr_start
,
i
,
curr_depth
,
longest_match_array
)
;
}
}
const
prev_depth
=
depth
[
depth
.
length
-
1
];
...
...
@@ -148,12 +160,15 @@ const compute_matches = (docs, min_length, allow_self_similarities) => {
curr_start
=
start
.
pop
();
curr_depth
=
depth
.
pop
();
}
}
else
i
++
}
else
i
++
;
}
const
matches
=
[];
match_groups
.
forEach
(([
index
,
match_length
,
end
])
=>
{
if
(
is_nested
(
index
,
end
,
match_length
,
suffix_array
,
inverse_suffix_array
,
longest_match_array
))
return
if
(
is_nested
(
index
,
end
,
match_length
,
suffix_array
,
inverse_suffix_array
,
longest_match_array
)
)
return
;
const
curr_matches
=
docs
.
map
(()
=>
[]);
let
pos
=
suffix_array
[
index
];
let
doc_idx
=
document_vector
[
pos
];
...
...
@@ -189,6 +204,12 @@ const insert_pos = (left, right, information, nodes) => {
nodes
.
splice
(
index
,
0
,
[
left
,
right
,
information
]);
};
const
nullify_tag_order
=
(
information
)
=>
{
const
newInformation
=
[...
information
];
newInformation
[
4
]
=
null
;
return
newInformation
;
};
const
_collapse
=
(
nodes
,
lower
,
upper
)
=>
{
const
results
=
[];
while
(
nodes
.
length
)
{
...
...
@@ -197,7 +218,7 @@ const _collapse = (nodes, lower, upper) => {
nodes
.
shift
();
if
(
right
>
upper
)
{
insert_pos
(
upper
+
1
,
right
,
information
,
nodes
);
nodes
.
unshift
([
left
,
upper
,
information
]);
nodes
.
unshift
([
left
,
upper
,
nullify_tag_order
(
information
)
]);
continue
;
}
const
children
=
_collapse
(
nodes
,
left
,
right
);
...
...
@@ -209,11 +230,13 @@ const _collapse = (nodes, lower, upper) => {
return
results
;
};
const
collapse
=
(
nodes
)
=>
{
// nest markups
const
collapse
=
(
nodes
,
max_tag
)
=>
{
let
tag_array
=
max_tag
?
Array
(
max_tag
).
fill
(
0
)
:
null
;
const
results
=
[];
while
(
nodes
.
length
)
{
const
range
=
nodes
.
shift
();
const
[
left
,
right
]
=
range
;
const
[
left
,
right
,
information
]
=
range
;
const
children
=
_collapse
(
nodes
,
left
,
right
);
if
(
children
.
length
)
range
.
push
(
children
);
results
.
push
(
range
);
...
...
@@ -221,6 +244,7 @@ const collapse = (nodes) => {
return
results
;
};
// resolve markup positions to words
const
translate
=
(
coll_markups
,
wstokens
)
=>
{
const
result
=
[];
let
last_end
=
0
;
...
...
@@ -300,16 +324,17 @@ const clean_list = (words) => {
return
[
tokens
,
idx
];
};
const
cyrb53
=
function
(
str
,
seed
=
0
)
{
let
h1
=
0xdeadbeef
^
seed
,
h2
=
0x41c6ce57
^
seed
;
for
(
let
i
=
0
,
ch
;
i
<
str
.
length
;
i
++
)
{
ch
=
str
.
charCodeAt
(
i
);
h1
=
Math
.
imul
(
h1
^
ch
,
2654435761
);
h2
=
Math
.
imul
(
h2
^
ch
,
1597334677
);
}
h1
=
Math
.
imul
(
h1
^
(
h1
>>>
16
),
2246822507
)
^
Math
.
imul
(
h2
^
(
h2
>>>
13
),
3266489909
);
h2
=
Math
.
imul
(
h2
^
(
h2
>>>
16
),
2246822507
)
^
Math
.
imul
(
h1
^
(
h1
>>>
13
),
3266489909
);
return
4294967296
*
(
2097151
&
h2
)
+
(
h1
>>>
0
);
const
cyrb53
=
function
(
str
,
seed
=
0
)
{
let
h1
=
0xdeadbeef
^
seed
,
h2
=
0x41c6ce57
^
seed
;
for
(
let
i
=
0
,
ch
;
i
<
str
.
length
;
i
++
)
{
ch
=
str
.
charCodeAt
(
i
);
h1
=
Math
.
imul
(
h1
^
ch
,
2654435761
);
h2
=
Math
.
imul
(
h2
^
ch
,
1597334677
);
}
h1
=
Math
.
imul
(
h1
^
(
h1
>>>
16
),
2246822507
)
^
Math
.
imul
(
h2
^
(
h2
>>>
13
),
3266489909
);
h2
=
Math
.
imul
(
h2
^
(
h2
>>>
16
),
2246822507
)
^
Math
.
imul
(
h1
^
(
h1
>>>
13
),
3266489909
);
return
4294967296
*
(
2097151
&
h2
)
+
(
h1
>>>
0
);
};
const
intToRGB
=
(
i
)
=>
{
...
...
@@ -336,7 +361,7 @@ const colorMarkup = (num) => {
return
[
`#
${
bgcolor
}
`
,
`#
${
fgcolor
}
`
];
};
const
computeMarkup
=
(
docs
,
min_length
,
allow_self_similarities
)
=>
{
const
computeMarkup
=
(
docs
,
min_length
=
3
,
allow_self_similarities
=
false
)
=>
{
const
textblocks
=
docs
.
map
((
doc
)
=>
new
Textblock
(
doc
));
const
clean_docs_idx
=
textblocks
.
map
((
textblock
)
=>
clean_list
(
textblock
.
words
));
...
...
@@ -349,14 +374,14 @@ const computeMarkup = (docs, min_length, allow_self_similarities) => {
let
tag
=
0
;
matches
.
forEach
(([
match_length
,
text
,
groups
])
=>
{
const
color
=
colorMarkup
(
cyrb53
(
text
));
const
groupSizes
=
groups
.
map
(
start
=>
start
.
length
)
const
groupSizes
=
groups
.
map
(
(
start
)
=>
start
.
length
)
;
groups
.
forEach
((
group
,
i
)
=>
{
group
.
sort
(
)
group
.
sort
(
(
a
,
b
)
=>
a
-
b
);
return
group
.
forEach
((
start
,
j
)
=>
{
const
map_start
=
clean_docs_idx
[
i
][
1
][
start
];
const
map_end
=
clean_docs_idx
[
i
][
1
][
start
+
match_length
-
1
];
textblocks
[
i
].
add_range
(
map_start
,
map_end
,
[
tag
,
...
color
,
j
,
groupSizes
]);
})
textblocks
[
i
].
add_range
(
map_start
,
map_end
,
[
tag
,
...
color
,
i
,
j
,
groupSizes
]);
})
;
});
tag
++
;
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment