Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
1635f714
Commit
1635f714
authored
Nov 01, 2022
by
Robert Knight
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert Guest class to TypeScript syntax
parent
445bfef7
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
194 additions
and
240 deletions
+194
-240
guest.ts
src/annotator/guest.ts
+194
-240
No files found.
src/annotator/guest.
j
s
→
src/annotator/guest.
t
s
View file @
1635f714
...
...
@@ -25,37 +25,33 @@ import { findClosestOffscreenAnchor } from './util/buckets';
import
{
frameFillsAncestor
}
from
'./util/frame'
;
import
{
normalizeURI
}
from
'./util/url'
;
/**
* @typedef {import('../types/annotator').AnnotationData} AnnotationData
* @typedef {import('../types/annotator').Annotator} Annotator
* @typedef {import('../types/annotator').Anchor} Anchor
* @typedef {import('../types/annotator').ContentInfoConfig} ContentInfoConfig
* @typedef {import('../types/annotator').Destroyable} Destroyable
* @typedef {import('../types/annotator').SidebarLayout} SidebarLayout
* @typedef {import('../types/api').Target} Target
* @typedef {import('../types/port-rpc-events').HostToGuestEvent} HostToGuestEvent
* @typedef {import('../types/port-rpc-events').GuestToHostEvent} GuestToHostEvent
* @typedef {import('../types/port-rpc-events').GuestToSidebarEvent} GuestToSidebarEvent
* @typedef {import('../types/port-rpc-events').SidebarToGuestEvent} SidebarToGuestEvent
*/
/**
* HTML element created by the highlighter with an associated annotation.
*
* @typedef {HTMLElement & { _annotation?: AnnotationData }} AnnotationHighlight
*/
/**
* Return all the annotations tags associated with the selected text.
*
* @return {string[]}
*/
function
annotationsForSelection
()
{
const
selection
=
/** @type {Selection} */
(
window
.
getSelection
());
import
type
{
AnnotationData
,
Annotator
,
Anchor
,
ContentInfoConfig
,
Destroyable
,
Integration
,
SidebarLayout
,
}
from
'../types/annotator'
;
import
type
{
Target
}
from
'../types/api'
;
import
type
{
HostToGuestEvent
,
GuestToHostEvent
,
GuestToSidebarEvent
,
SidebarToGuestEvent
,
}
from
'../types/port-rpc-events'
;
/** HTML element created by the highlighter with an associated annotation. */
type
AnnotationHighlight
=
HTMLElement
&
{
_annotation
?:
AnnotationData
};
/** Return all the annotations tags associated with the selected text. */
function
annotationsForSelection
():
string
[]
{
const
selection
=
window
.
getSelection
()
!
;
const
range
=
selection
.
getRangeAt
(
0
);
const
tags
=
rangeUtil
.
itemsForRange
(
range
,
node
=>
/** @type {AnnotationHighlight} */
(
node
).
_annotation
?.
$tag
node
=>
(
node
as
AnnotationHighlight
).
_annotation
?.
$tag
);
return
tags
;
}
...
...
@@ -63,16 +59,13 @@ function annotationsForSelection() {
/**
* Return the annotation tags associated with any highlights that contain a given
* DOM node.
*
* @param {Node} node
* @return {string[]}
*/
function
annotationsAt
(
node
)
{
function
annotationsAt
(
node
:
Node
):
string
[]
{
const
items
=
getHighlightsContainingNode
(
node
)
.
map
(
h
=>
/** @type {AnnotationHighlight} */
(
h
).
_annotation
)
.
map
(
h
=>
(
h
as
AnnotationHighlight
).
_annotation
)
.
filter
(
ann
=>
ann
!==
undefined
)
.
map
(
ann
=>
ann
?.
$tag
);
return
/** @type {string[]} */
(
items
)
;
return
items
as
string
[]
;
}
/**
...
...
@@ -80,11 +73,8 @@ function annotationsAt(node) {
*
* This may fail if anchoring failed or if the document has been mutated since
* the anchor was created in a way that invalidates the anchor.
*
* @param {Anchor} anchor
* @return {Range|null}
*/
function
resolveAnchor
(
anchor
)
{
function
resolveAnchor
(
anchor
:
Anchor
):
Range
|
null
{
if
(
!
anchor
.
range
)
{
return
null
;
}
...
...
@@ -101,14 +91,17 @@ function removeTextSelection() {
/**
* Subset of the Hypothesis client configuration that is used by {@link Guest}.
*
* @typedef GuestConfig
* @prop {string} [subFrameIdentifier] - An identifier used by this guest to
* identify the current frame when communicating with the sidebar. This is
* only set in non-host frames.
* @prop {ContentInfoConfig} [contentInfoBanner] - Configures a banner or other indicators
* showing where the content has come from.
*/
export
type
GuestConfig
=
{
/**
* An identifier used by this guest to identify the current frame when
* communicating with the sidebar. This is only set in non-host frames.
*/
subFrameIdentifier
?:
string
;
/** Configures a banner or other indicators showing where the content has come from. */
contentInfoBanner
?:
ContentInfoConfig
;
};
/**
* `Guest` is the central class of the annotator that handles anchoring (locating)
...
...
@@ -126,27 +119,83 @@ function removeTextSelection() {
* class that shows the sidebar app and surrounding UI. The `Guest` instance in
* each frame connects to the sidebar and host frames as part of its
* initialization.
*/
export
class
Guest
implements
Annotator
,
Destroyable
{
public
element
:
HTMLElement
;
/** Ranges of the current text selection. */
public
selectedRanges
:
Range
[];
/**
* The anchors generated by resolving annotation selectors to locations in the
* document. These are added by `anchor` and removed by `detach`.
*
* @implements {Annotator}
* @implements {Destroyable}
* There is one anchor per annotation `Target`, which typically means one
* anchor per annotation.
*/
export
class
Guest
{
public
anchors
:
Anchor
[];
public
features
:
FeatureFlags
;
private
_adder
:
Adder
;
private
_clusterToolbar
?:
HighlightClusterController
;
private
_hostFrame
:
Window
;
private
_highlightsVisible
:
boolean
;
private
_isAdderVisible
:
boolean
;
private
_informHostOnNextSelectionClear
:
boolean
;
private
_selectionObserver
:
SelectionObserver
;
/**
* @param {HTMLElement} element -
* Tags of annotations that are currently anchored or being anchored in
* the guest.
*/
private
_annotations
:
Set
<
string
>
;
private
_frameIdentifier
:
string
|
null
;
private
_portFinder
:
PortFinder
;
/**
* Integration that handles document-type specific functionality in the
* guest.
*/
private
_integration
:
Integration
;
/** Channel for host-guest communication. */
private
_hostRPC
:
PortRPC
<
HostToGuestEvent
,
GuestToHostEvent
>
;
/** Channel for guest-sidebar communication. */
private
_sidebarRPC
:
PortRPC
<
SidebarToGuestEvent
,
GuestToSidebarEvent
>
;
private
_bucketBarClient
:
BucketBarClient
;
private
_sideBySideActive
:
boolean
;
private
_listeners
:
ListenerCollection
;
/**
* Tags of currently hovered annotations. This is used to set the hovered
* state correctly for new highlights if the associated annotation is already
* hovered in the sidebar.
*/
private
_hoveredAnnotations
:
Set
<
string
>
;
/**
* @param element -
* The root element in which the `Guest` instance should be able to anchor
* or create annotations. In an ordinary web page this typically `document.body`.
* @param
{GuestConfig}
[config]
* @param
{Window}
[hostFrame] -
* @param [config]
* @param [hostFrame] -
* Host frame which this guest is associated with. This is expected to be
* an ancestor of the guest frame. It may be same or cross origin.
*/
constructor
(
element
,
config
=
{},
hostFrame
=
window
)
{
constructor
(
element
:
HTMLElement
,
config
:
GuestConfig
=
{},
hostFrame
:
Window
=
window
)
{
this
.
element
=
element
;
this
.
_hostFrame
=
hostFrame
;
this
.
_highlightsVisible
=
false
;
this
.
_isAdderVisible
=
false
;
this
.
_informHostOnNextSelectionClear
=
true
;
/** @type {Range[]} - Ranges of the current text selection. */
this
.
selectedRanges
=
[];
this
.
_adder
=
new
Adder
(
this
.
element
,
{
...
...
@@ -170,26 +219,11 @@ export class Guest {
}
});
/**
* The anchors generated by resolving annotation selectors to locations in the
* document. These are added by `anchor` and removed by `detach`.
*
* There is one anchor per annotation `Target`, which typically means one
* anchor per annotation.
*
* @type {Anchor[]}
*/
this
.
anchors
=
[];
/**
* Tags of annotations that are currently anchored or being anchored in
* the guest.
*/
this
.
_annotations
=
/** @type {Set<string>} */
(
new
Set
());
this
.
_annotations
=
new
Set
();
// Set the frame identifier if it's available.
// The "top" guest instance will have this as null since it's in a top frame not a sub frame
/** @type {string|null} */
this
.
_frameIdentifier
=
config
.
subFrameIdentifier
||
null
;
this
.
_portFinder
=
new
PortFinder
({
...
...
@@ -199,10 +233,7 @@ export class Guest {
});
this
.
features
=
new
FeatureFlags
();
/**
* Integration that handles document-type specific functionality in the
* guest.
*/
this
.
_integration
=
createIntegration
(
this
);
this
.
_integration
.
on
(
'uriChanged'
,
async
()
=>
{
const
metadata
=
await
this
.
getDocumentInfo
();
...
...
@@ -218,19 +249,9 @@ export class Guest {
});
}
/**
* Channel for host-guest communication.
*
* @type {PortRPC<HostToGuestEvent, GuestToHostEvent>}
*/
this
.
_hostRPC
=
new
PortRPC
();
this
.
_connectHost
(
hostFrame
);
/**
* Channel for guest-sidebar communication.
*
* @type {PortRPC<SidebarToGuestEvent, GuestToSidebarEvent>}
*/
this
.
_sidebarRPC
=
new
PortRPC
();
this
.
_connectSidebar
();
...
...
@@ -245,13 +266,6 @@ export class Guest {
this
.
_listeners
=
new
ListenerCollection
();
this
.
_setupElementEvents
();
/**
* Tags of currently hovered annotations. This is used to set the hovered
* state correctly for new highlights if the associated annotation is already
* hovered in the sidebar.
*
* @type {Set<string>}
*/
this
.
_hoveredAnnotations
=
new
Set
();
}
...
...
@@ -260,8 +274,7 @@ export class Guest {
_setupElementEvents
()
{
// Hide the sidebar in response to a document click or tap, so it doesn't obscure
// the document content.
/** @param {Element} element */
const
maybeCloseSidebar
=
element
=>
{
const
maybeCloseSidebar
=
(
element
:
Element
)
=>
{
if
(
this
.
_sideBySideActive
)
{
// Don't hide the sidebar if event was disabled because the sidebar
// doesn't overlap the content.
...
...
@@ -276,7 +289,7 @@ export class Guest {
this
.
_listeners
.
add
(
this
.
element
,
'mouseup'
,
event
=>
{
const
{
target
,
metaKey
,
ctrlKey
}
=
event
;
const
tags
=
annotationsAt
(
/** @type {Element} */
(
target
)
);
const
tags
=
annotationsAt
(
target
as
Element
);
if
(
tags
.
length
&&
this
.
_highlightsVisible
)
{
const
toggle
=
metaKey
||
ctrlKey
;
this
.
selectAnnotations
(
tags
,
{
toggle
});
...
...
@@ -284,17 +297,17 @@ export class Guest {
});
this
.
_listeners
.
add
(
this
.
element
,
'mousedown'
,
({
target
})
=>
{
maybeCloseSidebar
(
/** @type {Element} */
(
target
)
);
maybeCloseSidebar
(
target
as
Element
);
});
// Allow taps on the document to hide the sidebar as well as clicks.
// On iOS < 13 (2019), elements like h2 or div don't emit 'click' events.
this
.
_listeners
.
add
(
this
.
element
,
'touchstart'
,
({
target
})
=>
{
maybeCloseSidebar
(
/** @type {Element} */
(
target
)
);
maybeCloseSidebar
(
target
as
Element
);
});
this
.
_listeners
.
add
(
this
.
element
,
'mouseover'
,
({
target
})
=>
{
const
tags
=
annotationsAt
(
/** @type {Element} */
(
target
)
);
const
tags
=
annotationsAt
(
target
as
Element
);
if
(
tags
.
length
&&
this
.
_highlightsVisible
)
{
this
.
_sidebarRPC
.
call
(
'hoverAnnotations'
,
tags
);
}
...
...
@@ -343,8 +356,7 @@ export class Guest {
}
}
/** @param {Window} hostFrame */
async
_connectHost
(
hostFrame
)
{
async
_connectHost
(
hostFrame
:
Window
)
{
this
.
_hostRPC
.
on
(
'clearSelection'
,
()
=>
{
if
(
selectedRange
(
document
))
{
this
.
_informHostOnNextSelectionClear
=
false
;
...
...
@@ -354,39 +366,25 @@ export class Guest {
this
.
_hostRPC
.
on
(
'createAnnotation'
,
()
=>
this
.
createAnnotation
());
this
.
_hostRPC
.
on
(
'hoverAnnotations'
,
/** @param {string[]} tags */
tags
=>
this
.
_hoverAnnotations
(
tags
)
this
.
_hostRPC
.
on
(
'hoverAnnotations'
,
(
tags
:
string
[])
=>
this
.
_hoverAnnotations
(
tags
)
);
this
.
_hostRPC
.
on
(
'scrollToClosestOffScreenAnchor'
,
/**
* @param {string[]} tags
* @param {'down'|'up'} direction
*/
(
tags
,
direction
)
=>
this
.
_scrollToClosestOffScreenAnchor
(
tags
,
direction
)
(
tags
:
string
[],
direction
:
'down'
|
'up'
)
=>
this
.
_scrollToClosestOffScreenAnchor
(
tags
,
direction
)
);
this
.
_hostRPC
.
on
(
'selectAnnotations'
,
/**
* @param {string[]} tags
* @param {boolean} toggle
*/
(
tags
,
toggle
)
=>
this
.
selectAnnotations
(
tags
,
{
toggle
})
this
.
_hostRPC
.
on
(
'selectAnnotations'
,
(
tags
:
string
[],
toggle
:
boolean
)
=>
this
.
selectAnnotations
(
tags
,
{
toggle
})
);
this
.
_hostRPC
.
on
(
'sidebarLayoutChanged'
,
/** @param {SidebarLayout} sidebarLayout */
sidebarLayout
=>
{
this
.
_hostRPC
.
on
(
'sidebarLayoutChanged'
,
(
sidebarLayout
:
SidebarLayout
)
=>
{
if
(
frameFillsAncestor
(
window
,
hostFrame
))
{
this
.
fitSideBySide
(
sidebarLayout
);
}
}
);
});
// Discover and connect to the host frame. All RPC events must be
// registered before creating the channel.
...
...
@@ -397,22 +395,16 @@ export class Guest {
async
_connectSidebar
()
{
this
.
_sidebarRPC
.
on
(
'featureFlagsUpdated'
,
/** @param {Record<string, boolean>} flags */
flags
=>
this
.
features
.
update
(
flags
)
(
flags
:
Record
<
string
,
boolean
>
)
=>
this
.
features
.
update
(
flags
)
);
// Handlers for events sent when user hovers or clicks on an annotation card
// in the sidebar.
this
.
_sidebarRPC
.
on
(
'hoverAnnotations'
,
/** @param {string[]} tags */
tags
=>
this
.
_hoverAnnotations
(
tags
)
this
.
_sidebarRPC
.
on
(
'hoverAnnotations'
,
(
tags
:
string
[])
=>
this
.
_hoverAnnotations
(
tags
)
);
this
.
_sidebarRPC
.
on
(
'scrollToAnnotation'
,
/** @param {string} tag */
tag
=>
{
this
.
_sidebarRPC
.
on
(
'scrollToAnnotation'
,
(
tag
:
string
)
=>
{
const
anchor
=
this
.
anchors
.
find
(
a
=>
a
.
annotation
.
$tag
===
tag
);
if
(
!
anchor
?.
highlights
)
{
return
;
...
...
@@ -435,33 +427,21 @@ export class Guest {
if
(
defaultNotPrevented
)
{
this
.
_integration
.
scrollToAnchor
(
anchor
);
}
}
);
});
// Handler for controls on the sidebar
this
.
_sidebarRPC
.
on
(
'setHighlightsVisible'
,
/** @param {boolean} showHighlights */
showHighlights
=>
{
this
.
_sidebarRPC
.
on
(
'setHighlightsVisible'
,
(
showHighlights
:
boolean
)
=>
{
this
.
setHighlightsVisible
(
showHighlights
,
false
/* notifyHost */
);
}
);
});
this
.
_sidebarRPC
.
on
(
'deleteAnnotation'
,
/** @param {string} tag */
tag
=>
this
.
detach
(
tag
)
);
this
.
_sidebarRPC
.
on
(
'deleteAnnotation'
,
(
tag
:
string
)
=>
this
.
detach
(
tag
));
this
.
_sidebarRPC
.
on
(
'loadAnnotations'
,
/** @param {AnnotationData[]} annotations */
annotations
=>
annotations
.
forEach
(
annotation
=>
this
.
anchor
(
annotation
))
this
.
_sidebarRPC
.
on
(
'loadAnnotations'
,
(
annotations
:
AnnotationData
[])
=>
annotations
.
forEach
(
annotation
=>
this
.
anchor
(
annotation
))
);
this
.
_sidebarRPC
.
on
(
'showContentInfo'
,
/** @param {ContentInfoConfig} info */
info
=>
this
.
_integration
.
showContentInfo
?.(
info
)
this
.
_sidebarRPC
.
on
(
'showContentInfo'
,
(
info
:
ContentInfoConfig
)
=>
this
.
_integration
.
showContentInfo
?.(
info
)
);
// Connect to sidebar and send document info/URIs to it.
...
...
@@ -501,18 +481,12 @@ export class Guest {
*
* Any existing anchors associated with `annotation` will be removed before
* re-anchoring the annotation.
*
* @param {AnnotationData} annotation
* @return {Promise<Anchor[]>}
*/
async
anchor
(
annotation
)
{
async
anchor
(
annotation
:
AnnotationData
):
Promise
<
Anchor
[]
>
{
/**
* Resolve an annotation's selectors to a concrete range.
*
* @param {Target} target
* @return {Promise<Anchor>}
*/
const
locate
=
async
target
=>
{
const
locate
=
async
(
target
:
Target
):
Promise
<
Anchor
>
=>
{
// Only annotations with an associated quote can currently be anchored.
// This is because the quote is used to verify anchoring with other selector
// types.
...
...
@@ -523,8 +497,7 @@ export class Guest {
return
{
annotation
,
target
};
}
/** @type {Anchor} */
let
anchor
;
let
anchor
:
Anchor
;
try
{
const
range
=
await
this
.
_integration
.
anchor
(
this
.
element
,
...
...
@@ -544,21 +517,17 @@ export class Guest {
/**
* Highlight the text range that `anchor` refers to.
*
* @param {Anchor} anchor
*/
const
highlight
=
anchor
=>
{
const
highlight
=
(
anchor
:
Anchor
)
=>
{
const
range
=
resolveAnchor
(
anchor
);
if
(
!
range
)
{
return
;
}
const
highlights
=
/** @type {AnnotationHighlight[]} */
(
highlightRange
(
const
highlights
=
highlightRange
(
range
,
classnames
(
'hypothesis-highlight'
,
anchor
.
annotation
?.
$cluster
)
)
);
)
as
AnnotationHighlight
[];
highlights
.
forEach
(
h
=>
{
h
.
_annotation
=
anchor
.
annotation
;
});
...
...
@@ -585,7 +554,7 @@ export class Guest {
return
[];
}
for
(
le
t
anchor
of
anchors
)
{
for
(
cons
t
anchor
of
anchors
)
{
highlight
(
anchor
);
}
...
...
@@ -607,16 +576,14 @@ export class Guest {
/**
* Remove the anchors and associated highlights for an annotation from the document.
*
* @param {string} tag
* @param {boolean} [notify] - For internal use. Whether to inform the host
* @param [notify] - For internal use. Whether to inform the host
* frame about the removal of an anchor.
*/
detach
(
tag
,
notify
=
true
)
{
detach
(
tag
:
string
,
notify
=
true
)
{
this
.
_annotations
.
delete
(
tag
);
/** @type {Anchor[]} */
const
anchors
=
[];
for
(
let
anchor
of
this
.
anchors
)
{
const
anchors
=
[]
as
Anchor
[];
for
(
const
anchor
of
this
.
anchors
)
{
if
(
anchor
.
annotation
.
$tag
!==
tag
)
{
anchors
.
push
(
anchor
);
}
else
if
(
anchor
.
highlights
)
{
...
...
@@ -626,11 +593,7 @@ export class Guest {
this
.
_updateAnchors
(
anchors
,
notify
);
}
/**
* @param {Anchor[]} anchors
* @param {boolean} notify
*/
_updateAnchors
(
anchors
,
notify
)
{
_updateAnchors
(
anchors
:
Anchor
[],
notify
:
boolean
)
{
this
.
anchors
=
anchors
;
if
(
notify
)
{
this
.
_bucketBarClient
.
update
(
this
.
anchors
);
...
...
@@ -641,13 +604,13 @@ export class Guest {
* Create a new annotation that is associated with the selected region of
* the current document.
*
* @param
{object}
options
* @param
{boolean}
[options.highlight] - If true, the new annotation has
* @param options
* @param [options.highlight] - If true, the new annotation has
* the `$highlight` flag set, causing it to be saved immediately without
* prompting for a comment.
* @return
{Promise<AnnotationData>} -
The new annotation
* @return The new annotation
*/
async
createAnnotation
({
highlight
=
false
}
=
{})
{
async
createAnnotation
({
highlight
=
false
}
=
{})
:
Promise
<
AnnotationData
>
{
const
ranges
=
this
.
selectedRanges
;
this
.
selectedRanges
=
[];
...
...
@@ -664,8 +627,7 @@ export class Guest {
selector
:
selectors
,
}));
/** @type {AnnotationData} */
const
annotation
=
{
const
annotation
:
AnnotationData
=
{
uri
:
info
.
uri
,
document
:
info
.
metadata
,
target
,
...
...
@@ -687,14 +649,12 @@ export class Guest {
/**
* Indicate in the sidebar that certain annotations are focused (ie. the
* associated document region(s) is hovered).
*
* @param {string[]} tags
*/
_hoverAnnotations
(
tags
)
{
_hoverAnnotations
(
tags
:
string
[]
)
{
this
.
_hoveredAnnotations
.
clear
();
tags
.
forEach
(
tag
=>
this
.
_hoveredAnnotations
.
add
(
tag
));
for
(
le
t
anchor
of
this
.
anchors
)
{
for
(
cons
t
anchor
of
this
.
anchors
)
{
if
(
anchor
.
highlights
)
{
const
toggle
=
tags
.
includes
(
anchor
.
annotation
.
$tag
);
setHighlightsFocused
(
anchor
.
highlights
,
toggle
);
...
...
@@ -706,11 +666,8 @@ export class Guest {
/**
* Scroll to the closest off screen anchor.
*
* @param {string[]} tags
* @param {'down'|'up'} direction
*/
_scrollToClosestOffScreenAnchor
(
tags
,
direction
)
{
_scrollToClosestOffScreenAnchor
(
tags
:
string
[],
direction
:
'down'
|
'up'
)
{
const
anchors
=
this
.
anchors
.
filter
(({
annotation
})
=>
tags
.
includes
(
annotation
.
$tag
)
);
...
...
@@ -722,16 +679,14 @@ export class Guest {
/**
* Show or hide the adder toolbar when the selection changes.
*
* @param {Range} range
*/
_onSelection
(
range
)
{
_onSelection
(
range
:
Range
)
{
if
(
!
this
.
_integration
.
canAnnotate
(
range
))
{
this
.
_onClearSelection
();
return
;
}
const
selection
=
/** @type {Selection} */
(
document
.
getSelection
())
;
const
selection
=
document
.
getSelection
()
!
;
const
isBackwards
=
rangeUtil
.
isSelectionBackwards
(
selection
);
const
focusRect
=
rangeUtil
.
selectionFocusRect
(
selection
);
if
(
!
focusRect
)
{
...
...
@@ -765,15 +720,18 @@ export class Guest {
* and opens the sidebar. Optionally it can also transfer keyboard focus to
* the annotation card for the first selected annotation.
*
* @param
{string[]}
tags
* @param
{object}
options
* @param
{boolean}
[options.toggle] - Toggle whether the annotations are
* @param tags
* @param options
* @param [options.toggle] - Toggle whether the annotations are
* selected, as opposed to just selecting them
* @param
{boolean}
[options.focusInSidebar] - Whether to transfer keyboard
* @param [options.focusInSidebar] - Whether to transfer keyboard
* focus to the card for the first annotation in the selection. This
* option has no effect if {@link toggle} is true.
*/
selectAnnotations
(
tags
,
{
toggle
=
false
,
focusInSidebar
=
false
}
=
{})
{
selectAnnotations
(
tags
:
string
[],
{
toggle
=
false
,
focusInSidebar
=
false
}
=
{}
)
{
if
(
toggle
)
{
this
.
_sidebarRPC
.
call
(
'toggleAnnotationSelection'
,
tags
);
}
else
{
...
...
@@ -785,12 +743,12 @@ export class Guest {
/**
* Set whether highlights are visible in the document or not.
*
* @param
{boolean}
visible
* @param
{boolean}
notifyHost - Whether to notify the host frame about this
* @param visible
* @param notifyHost - Whether to notify the host frame about this
* change. This should be true unless the request to change highlight
* visibility is coming from the host frame.
*/
setHighlightsVisible
(
visible
,
notifyHost
=
true
)
{
setHighlightsVisible
(
visible
:
boolean
,
notifyHost
=
true
)
{
setHighlightsVisible
(
this
.
element
,
visible
);
this
.
_highlightsVisible
=
visible
;
if
(
notifyHost
)
{
...
...
@@ -805,9 +763,9 @@ export class Guest {
/**
* Attempt to fit the document content alongside the sidebar.
*
* @param
{SidebarLayout}
sidebarLayout
* @param sidebarLayout
*/
fitSideBySide
(
sidebarLayout
)
{
fitSideBySide
(
sidebarLayout
:
SidebarLayout
)
{
this
.
_sideBySideActive
=
this
.
_integration
.
fitSideBySide
(
sidebarLayout
);
}
...
...
@@ -825,19 +783,15 @@ export class Guest {
/**
* Return the tags of annotations that are currently displayed in a hovered
* state.
*
* @return {Set<string>}
*/
get
hoveredAnnotationTags
()
{
get
hoveredAnnotationTags
()
:
Set
<
string
>
{
return
this
.
_hoveredAnnotations
;
}
/**
* Handle a potential shortcut trigger.
*
* @param {KeyboardEvent} event
*/
_handleShortcut
(
event
)
{
_handleShortcut
(
event
:
KeyboardEvent
)
{
if
(
matchShortcut
(
event
,
'Ctrl+Shift+H'
))
{
this
.
setHighlightsVisible
(
!
this
.
_highlightsVisible
);
}
...
...
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