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
be0d5b0c
Commit
be0d5b0c
authored
Sep 01, 2023
by
Robert Knight
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert boot script modules to TypeScript
parent
45fe9d7f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
67 additions
and
97 deletions
+67
-97
rollup-boot.config.mjs
rollup-boot.config.mjs
+1
-1
boot.ts
src/boot/boot.ts
+53
-69
browser-check.ts
src/boot/browser-check.ts
+1
-3
index.ts
src/boot/index.ts
+6
-10
parse-json-config.ts
src/boot/parse-json-config.ts
+3
-4
url-template.ts
src/boot/url-template.ts
+3
-10
No files found.
rollup-boot.config.mjs
View file @
be0d5b0c
...
...
@@ -36,7 +36,7 @@ const assetRoot = isProd
:
`
${
localhost
}
:3001/hypothesis/
${
version
}
/`
;
export
default
{
input
:
'src/boot/index.
j
s'
,
input
:
'src/boot/index.
t
s'
,
output
:
{
file
:
'build/boot.js'
,
...
...
src/boot/boot.
j
s
→
src/boot/boot.
t
s
View file @
be0d5b0c
/**
* @typedef SidebarAppConfig
* @prop {string} assetRoot - The root URL to which URLs in `manifest` are relative
* @prop {Record<string,string>} manifest -
* A mapping from canonical asset path to cache-busted asset path
* @prop {string} apiUrl
*/
/**
* @typedef AnnotatorConfig
* @prop {string} assetRoot - The root URL to which URLs in `manifest` are relative
* @prop {string} notebookAppUrl - The URL of the sidebar's notebook
* @prop {string} profileAppUrl - The URL of the sidebar's user profile view
* @prop {string} sidebarAppUrl - The URL of the sidebar's HTML page
* @prop {Record<string,string>} manifest -
* A mapping from canonical asset path to cache-busted asset path
*/
/**
* @typedef {Window & { PDFViewerApplication?: object }} MaybePDFWindow
*/
export
type
SidebarAppConfig
=
{
/** The root URL to which URLs in `manifest` are relative. */
assetRoot
:
string
;
/** A mapping from canonical asset path to cache-busted asset path. */
manifest
:
Record
<
string
,
string
>
;
apiUrl
:
string
;
};
export
type
AnnotatorConfig
=
{
/** The root URL to which URLs in `manifest` are relative. */
assetRoot
:
string
;
/** The URL of the sidebar's notebook. */
notebookAppUrl
:
string
;
/** The URL of the sidebar's user profile view. */
profileAppUrl
:
string
;
/** The URL of the sidebar's HTML page. */
sidebarAppUrl
:
string
;
/** A mapping from canonical asset path to cache-busted asset path. */
manifest
:
Record
<
string
,
string
>
;
};
type
MaybePDFWindow
=
Window
&
{
PDFViewerApplication
?:
object
};
/**
* Mark an element as having been added by the boot script.
*
* This marker is later used to know which elements to remove when unloading
* the client.
*
* @param {HTMLElement} el
*/
function
tagElement
(
el
)
{
function
tagElement
(
el
:
HTMLElement
)
{
el
.
setAttribute
(
'data-hypothesis-asset'
,
''
);
}
/**
* @param {Document} doc
* @param {string} href
*/
function
injectStylesheet
(
doc
,
href
)
{
function
injectStylesheet
(
doc
:
Document
,
href
:
string
)
{
const
link
=
doc
.
createElement
(
'link'
);
link
.
rel
=
'stylesheet'
;
link
.
type
=
'text/css'
;
...
...
@@ -46,14 +42,19 @@ function injectStylesheet(doc, href) {
doc
.
head
.
appendChild
(
link
);
}
/**
* @param {Document} doc
* @param {string} src - The script URL
* @param {object} options
* @param {boolean} [options.esModule] - Whether to load the script as an ES module
* @param {boolean} [options.forceReload] - Whether to force re-evaluation of an ES module script
*/
function
injectScript
(
doc
,
src
,
{
esModule
=
true
,
forceReload
=
false
}
=
{})
{
function
injectScript
(
doc
:
Document
,
src
:
string
,
{
esModule
=
true
,
forceReload
=
false
,
}:
{
/** Whether to load the script as an ES module. */
esModule
?:
boolean
;
/** Whether to force re-evaluation of an ES module script. */
forceReload
?:
boolean
;
}
=
{},
)
{
const
script
=
doc
.
createElement
(
'script'
);
if
(
esModule
)
{
...
...
@@ -79,13 +80,12 @@ function injectScript(doc, src, { esModule = true, forceReload = false } = {}) {
doc
.
head
.
appendChild
(
script
);
}
/**
* @param {Document} doc
* @param {string} rel
* @param {'html'|'javascript'} type
* @param {string} url
*/
function
injectLink
(
doc
,
rel
,
type
,
url
)
{
function
injectLink
(
doc
:
Document
,
rel
:
string
,
type
:
'html'
|
'javascript'
,
url
:
string
,
)
{
const
link
=
doc
.
createElement
(
'link'
);
link
.
rel
=
rel
;
link
.
href
=
url
;
...
...
@@ -100,12 +100,8 @@ function injectLink(doc, rel, type, url) {
*
* This can be used to preload an API request or other resource which we know
* that the client will load.
*
* @param {Document} doc
* @param {string} type - Type of resource
* @param {string} url
*/
function
preloadURL
(
doc
,
type
,
url
)
{
function
preloadURL
(
doc
:
Document
,
type
:
string
,
url
:
string
)
{
const
link
=
doc
.
createElement
(
'link'
);
link
.
rel
=
'preload'
;
link
.
as
=
type
;
...
...
@@ -122,11 +118,7 @@ function preloadURL(doc, type, url) {
doc
.
head
.
appendChild
(
link
);
}
/**
* @param {SidebarAppConfig|AnnotatorConfig} config
* @param {string} path
*/
function
assetURL
(
config
,
path
)
{
function
assetURL
(
config
:
SidebarAppConfig
|
AnnotatorConfig
,
path
:
string
)
{
return
config
.
assetRoot
+
'build/'
+
config
.
manifest
[
path
];
}
...
...
@@ -136,11 +128,8 @@ function assetURL(config, path) {
* This triggers loading of the necessary resources for the client in a host
* or guest frame. We could in future simplify booting in guest-only frames
* by omitting resources that are only needed in the host frame.
*
* @param {Document} doc
* @param {AnnotatorConfig} config
*/
export
function
bootHypothesisClient
(
doc
,
c
onfig
)
{
export
function
bootHypothesisClient
(
doc
:
Document
,
config
:
AnnotatorC
onfig
)
{
// Detect presence of Hypothesis in the page
const
appLinkEl
=
doc
.
querySelector
(
'link[type="application/annotator+html"]'
,
...
...
@@ -173,19 +162,17 @@ export function bootHypothesisClient(doc, config) {
);
const
scripts
=
[
'scripts/annotator.bundle.js'
];
for
(
le
t
path
of
scripts
)
{
for
(
cons
t
path
of
scripts
)
{
const
url
=
assetURL
(
config
,
path
);
injectScript
(
doc
,
url
,
{
esModule
:
false
});
}
const
styles
=
[];
if
(
/** @type {MaybePDFWindow} */
(
window
).
PDFViewerApplication
!==
undefined
)
{
if
((
window
as
MaybePDFWindow
).
PDFViewerApplication
!==
undefined
)
{
styles
.
push
(
'styles/pdfjs-overrides.css'
);
}
styles
.
push
(
'styles/highlights.css'
);
for
(
le
t
path
of
styles
)
{
for
(
cons
t
path
of
styles
)
{
const
url
=
assetURL
(
config
,
path
);
injectStylesheet
(
doc
,
url
);
}
...
...
@@ -193,23 +180,20 @@ export function bootHypothesisClient(doc, config) {
/**
* Bootstrap the sidebar application which displays annotations.
*
* @param {Document} doc
* @param {SidebarAppConfig} config
*/
export
function
bootSidebarApp
(
doc
,
c
onfig
)
{
export
function
bootSidebarApp
(
doc
:
Document
,
config
:
SidebarAppC
onfig
)
{
// Preload `/api/` and `/api/links` API responses.
preloadURL
(
doc
,
'fetch'
,
config
.
apiUrl
);
preloadURL
(
doc
,
'fetch'
,
config
.
apiUrl
+
'links'
);
const
scripts
=
[
'scripts/sidebar.bundle.js'
];
for
(
le
t
path
of
scripts
)
{
for
(
cons
t
path
of
scripts
)
{
const
url
=
assetURL
(
config
,
path
);
injectScript
(
doc
,
url
,
{
esModule
:
true
});
}
const
styles
=
[
'styles/katex.min.css'
,
'styles/sidebar.css'
];
for
(
le
t
path
of
styles
)
{
for
(
cons
t
path
of
styles
)
{
const
url
=
assetURL
(
config
,
path
);
injectStylesheet
(
doc
,
url
);
}
...
...
src/boot/browser-check.
j
s
→
src/boot/browser-check.
t
s
View file @
be0d5b0c
...
...
@@ -5,10 +5,8 @@
* We use feature tests to try to avoid false negatives, accepting some risk of
* false positives due to the host page having loaded polyfills for APIs in order
* to support older browsers.
*
* @return {boolean}
*/
export
function
isBrowserSupported
()
{
export
function
isBrowserSupported
()
:
boolean
{
// Checks that return a truthy value if they succeed and throw or return
// a falsey value if they fail.
const
checks
=
[
...
...
src/boot/index.
j
s
→
src/boot/index.
t
s
View file @
be0d5b0c
...
...
@@ -8,26 +8,22 @@
// @ts-ignore - This file is generated before the boot bundle is built.
import
manifest
from
'../../build/manifest.json'
;
import
{
bootHypothesisClient
,
bootSidebarApp
}
from
'./boot'
;
import
type
{
AnnotatorConfig
,
SidebarAppConfig
}
from
'./boot'
;
import
{
isBrowserSupported
}
from
'./browser-check'
;
import
{
getExtensionId
,
hasExtensionConfig
}
from
'./browser-extension-utils'
;
import
{
parseJsonConfig
}
from
'./parse-json-config'
;
import
{
processUrlTemplate
}
from
'./url-template'
;
/**
* @typedef {import('./boot').AnnotatorConfig} AnnotatorConfig
* @typedef {import('./boot').SidebarAppConfig} SidebarAppConfig
*/
if
(
isBrowserSupported
())
{
const
config
=
/** @type {AnnotatorConfig|SidebarAppConfig} */
(
parseJsonConfig
(
document
)
)
;
const
config
=
parseJsonConfig
(
document
)
as
|
AnnotatorConfig
|
SidebarAppConfig
;
const
assetRoot
=
processUrlTemplate
(
config
.
assetRoot
||
'__ASSET_ROOT__'
);
// Check whether this is a mini-app (indicated by the presence of a
// `<hypothesis-app>` element) and load the appropriate part of the client.
if
(
document
.
querySelector
(
'hypothesis-app'
))
{
const
sidebarConfig
=
/** @type {SidebarAppConfig} */
(
config
)
;
const
sidebarConfig
=
config
as
SidebarAppConfig
;
bootSidebarApp
(
document
,
{
assetRoot
,
manifest
,
...
...
@@ -45,7 +41,7 @@ if (isBrowserSupported()) {
// nb. If new asset URLs are added here, the browser extension and
// `hypothesis-injector.ts` need to be updated.
const
annotatorConfig
=
/** @type {AnnotatorConfig} */
(
config
)
;
const
annotatorConfig
=
config
as
AnnotatorConfig
;
const
notebookAppUrl
=
processUrlTemplate
(
annotatorConfig
.
notebookAppUrl
||
'__NOTEBOOK_APP_URL__'
,
);
...
...
src/boot/parse-json-config.
j
s
→
src/boot/parse-json-config.
t
s
View file @
be0d5b0c
...
...
@@ -12,11 +12,10 @@
* setting names, scripts further down in the document override those further
* up).
*
* @param
{Document|Element}
document - The root element to search.
* @param document - The root element to search.
*/
export
function
parseJsonConfig
(
document
)
{
/** @type {Record<string, unknown>} */
const
config
=
{};
export
function
parseJsonConfig
(
document
:
Document
|
Element
)
{
const
config
:
Record
<
string
,
unknown
>
=
{};
const
settingsElements
=
document
.
querySelectorAll
(
'script.js-hypothesis-config'
,
);
...
...
src/boot/url-template.
j
s
→
src/boot/url-template.
t
s
View file @
be0d5b0c
...
...
@@ -4,10 +4,8 @@
* We don't use the URL constructor here because IE and early versions of Edge
* do not support it and this code runs early in the life of the app before any
* polyfills can be loaded.
*
* @param {string} url
*/
function
extractOrigin
(
url
)
{
function
extractOrigin
(
url
:
string
)
{
const
match
=
url
.
match
(
/
(
https
?)
:
\/\/([^
:
/]
+
)
/
);
if
(
!
match
)
{
return
null
;
...
...
@@ -16,9 +14,7 @@ function extractOrigin(url) {
}
function
currentScriptOrigin
(
document_
=
document
)
{
const
scriptEl
=
/** @type {HTMLScriptElement|null} */
(
document_
.
currentScript
);
const
scriptEl
=
document_
.
currentScript
as
HTMLScriptElement
|
null
;
if
(
!
scriptEl
)
{
// Function was called outside of initial script execution.
return
null
;
...
...
@@ -34,11 +30,8 @@ function currentScriptOrigin(document_ = document) {
* from a device or VM that is not the system where the development server is
* running. In that case, all references to `localhost` need to be replaced
* with the IP/hostname of the dev server.
*
* @param {string} url
* @param {Document} document_
*/
export
function
processUrlTemplate
(
url
,
document_
=
document
)
{
export
function
processUrlTemplate
(
url
:
string
,
document_
=
document
)
{
if
(
url
.
indexOf
(
'{'
)
===
-
1
)
{
// Not a template. This should always be the case in production.
return
url
;
...
...
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