Unverified Commit 1b2cd85e authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #2268 from hypothesis/add-config-types

Begin to add JSDoc types for client configuration objects
parents 487a1b43 2ae8d153
......@@ -6,44 +6,13 @@ import {
toString,
} from '../shared/type-coercions';
/**
* @typedef RequestConfigFromFrameOptions
* @prop {number} ancestorLevel
* @prop {string} origin
*/
/**
* Configuration for the client provided by the frame embedding it.
*
* User-facing documentation exists at
* https://h.readthedocs.io/projects/client/en/latest/publishers/config/
*
* @typedef Config
* @prop {string} [annotations] - Direct-linked annotation ID
* @prop {string} [group] - Direct-linked group ID
* @prop {string} [query] - Initial filter query
* @prop {string} [appType] - Method used to load the client
* @prop {boolean} [openSidebar] - Whether to open the sidebar on the initial load
* @prop {boolean} [showHighlights] - Whether to show highlights
* @prop {Object[]} [services] -
* Configuration for the annotation services that the client connects to
* @prop {Object} [branding] -
* Theme properties (fonts, colors etc.)
* @prop {boolean} [enableExperimentalNewNoteButton] -
* Whether to show the "New note" button on the "Page Notes" tab
* @prop {RequestConfigFromFrameOptions|string} [requestConfigFromFrame]
* Origin of the ancestor frame to request configuration from
* @prop {string} [theme]
* Name of the base theme to use.
* @prop {string} [usernameUrl]
* URL template for username links
*/
/** @typedef {import('../types/config').HostConfig} HostConfig */
/**
* Return the app configuration specified by the frame embedding the Hypothesis
* client.
*
* @return {Config}
* @return {HostConfig}
*/
export default function hostPageConfig(window) {
const configStr = window.location.hash.slice(1);
......
/**
* @typedef {import('../types/config').HostConfig} HostConfig
* @typedef {import('../types/config').Service} Service
*/
/**
* Return the configuration for the annotation service which the client would retrieve
* annotations from which may contain the authority, grantToken and icon.
*
* @param {Object} settings - The settings object which would contain the services array.
* @param {HostConfig} settings
* @return {Service|null}
*/
export default function serviceConfig(settings) {
......
/**
* @typedef {import('../../types/config').HostConfig} HostConfig
*/
import serviceConfig from '../service-config';
/**
* Is the sharing of annotations enabled? Check for any defined `serviceConfig`,
* but default to `true` if none found.
*
* @param {object} settings
* @param {HostConfig} settings
* @return {boolean}
*/
export function sharingEnabled(settings) {
......@@ -35,7 +39,7 @@ export function shareURI(annotation) {
* and the annotation itself needs to have a sharing URI.
*
* @param {object} annotation
* @param {object} settings
* @param {HostConfig} settings
* @return {boolean}
*/
export function isShareable(annotation, settings) {
......
......@@ -2,6 +2,11 @@ import getApiUrl from '../get-api-url';
import hostConfig from '../host-config';
import * as postMessageJsonRpc from './postmessage-json-rpc';
/**
* @typedef {import('../../types/config').SidebarConfig} SidebarConfig
* @typedef {import('../../types/config').MergedConfig} MergedConfig
*/
/**
* @deprecated
*/
......@@ -180,9 +185,9 @@ async function fetchGroupsAsync(config, rpcCall) {
* Legacy RPC with unknown parent - From a ancestor parent frame that passes it down via RPC. (deprecated)
* RPC with known parent - From a ancestor parent frame that passes it down via RPC.
*
* @param {Object} appConfig - Settings rendered into `app.html` by the h service.
* @param {SidebarConfig} appConfig
* @param {Window} window_ - Test seam.
* @return {Promise<Object>} - The merged settings.
* @return {Promise<MergedConfig>} - The merged settings.
*/
export async function fetchConfig(appConfig, window_ = window) {
const hostPageConfig = hostConfig(window);
......
/** @typedef {import('../../types/api').Group} Group */
/**
* @typedef {import('../../types/config').HostConfig} HostConfig
* @typedef {import('../../types/api').Group} Group
*/
import escapeStringRegexp from 'escape-string-regexp';
import serviceConfig from '../service-config';
......@@ -9,14 +12,15 @@ import serviceConfig from '../service-config';
* explicitly disallowed in the service configuration of the
* `settings` object.
*
* @param {object} settings
* @param {HostConfig} settings
* @return {boolean}
*/
function allowLeavingGroups(settings) {
const config = serviceConfig(settings) || {};
return typeof config.allowLeavingGroups === 'boolean'
? config.allowLeavingGroups
: true;
const config = serviceConfig(settings);
if (!config) {
return true;
}
return !!config.allowLeavingGroups;
}
/**
......@@ -28,7 +32,7 @@ function allowLeavingGroups(settings) {
* @param {Group[]} userGroups - groups the user is a member of
* @param {Group[]} featuredGroups - all other groups, may include some duplicates from the userGroups
* @param {string} uri - uri of the current page
* @param {object} settings - The settings object.
* @param {HostConfig} settings
*/
export function combineGroups(userGroups, featuredGroups, uri, settings) {
const worldGroup = featuredGroups.find(g => g.id === '__world__');
......
/**
* @typedef {import('../../types/config').MergedConfig} MergedConfig
*/
import serviceConfig from '../service-config';
/**
......@@ -8,7 +12,7 @@ import serviceConfig from '../service-config';
*
* If no custom annotation services are configured then return `false`.
*
* @param {Object} settings - the sidebar settings object
* @param {MergedConfig} settings
* @return {boolean}
*/
export default function isThirdPartyService(settings) {
......
import serviceConfig from '../service-config';
/** @typedef {import('../../types/api').Profile} Profile */
/**
* @typedef {import('../../types/config').HostConfig} HostConfig
* @typedef {import('../../types/api').Profile} Profile
*/
/**
* Returns true if the sidebar tutorial has to be shown to a user for a given session.
......@@ -28,14 +31,15 @@ export function shouldShowSidebarTutorial(sessionState) {
*
* @param {boolean} isSidebar - is the app currently displayed in a sidebar?
* @param {Profile} profile - User profile returned from the API
* @param {Object} settings - app configuration/settings
* @param {HostConfig} settings
* @return {boolean} - Tutorial panel should be displayed automatically
*/
export function shouldAutoDisplayTutorial(isSidebar, profile, settings) {
const shouldShowBasedOnProfile =
typeof profile.preferences === 'object' &&
!!profile.preferences.show_sidebar_tutorial;
const service = serviceConfig(settings) || {};
const service = serviceConfig(settings) || { onHelpRequestProvided: false };
return (
isSidebar && !service.onHelpRequestProvided && shouldShowBasedOnProfile
);
......
/**
* Configuration for an annotation service.
*
* See https://h.readthedocs.io/projects/client/en/latest/publishers/config/#cmdoption-arg-services
*
* The `onXXX` functions may be set by the embedder of the client. The
* `onXXXProvided` booleans are correspondingly set in the annotator if a
* particular function is provided.
*
* @typedef Service
* @prop {string} apiUrl
* @prop {string} authority
* @prop {string} grantToken
* @prop {boolean} [allowLeavingGroups]
* @prop {boolean} [enableShareLinks]
* @prop {Function} [onLoginRequest]
* @prop {boolean} [onLoginRequestProvided]
* @prop {Function} [onLogoutRequest]
* @prop {boolean} [onLogoutRequestProvided]
* @prop {Function} [onSignupRequest]
* @prop {boolean} [onSignupRequestProvided]
* @prop {Function} [onProfileRequest]
* @prop {boolean} [onProfileRequestProvided]
* @prop {Function} [onHelpRequest]
* @prop {boolean} [onHelpRequestProvided]
*/
/**
* Configuration for the Sentry crash-reporting service.
*
* @typedef SentryConfig
* @prop {string} dsn
* @prop {string} environment
*/
/**
* Configuration for the sidebar app set by the Hypothesis backend ("h")
* or baked into the sidebar app at build time (in the browser extension).
*
* See `h.views.client` in the "h" application.
*
* @typedef SidebarConfig
* @prop {string} apiUrl
* @prop {string} authDomain
* @prop {string} [googleAnalytics]
* @prop {string} oauthClientId
* @prop {string[]} rpcAllowedOrigins
* @prop {SentryConfig} [sentry]
* @prop {string} [websocketUrl]
*/
/**
* @typedef RequestConfigFromFrameOptions
* @prop {number} ancestorLevel
* @prop {string} origin
*/
/**
* Configuration set by the embedder of the client and used by the sidebar.
*
* This is the subset of keys from
* https://h.readthedocs.io/projects/client/en/latest/publishers/config/ which
* excludes any keys used only by the "annotator" part of the application.
*
* @typedef HostConfig
* @prop {string} [annotations] - Direct-linked annotation ID
* @prop {string} [group] - Direct-linked group ID
* @prop {string} [query] - Initial filter query
* @prop {string} [appType] - Method used to load the client
* @prop {boolean} [openSidebar] - Whether to open the sidebar on the initial load
* @prop {boolean} [showHighlights] - Whether to show highlights
* @prop {Object} [branding] -
* Theme properties (fonts, colors etc.)
* @prop {boolean} [enableExperimentalNewNoteButton] -
* Whether to show the "New note" button on the "Page Notes" tab
* @prop {RequestConfigFromFrameOptions|string} [requestConfigFromFrame]
* Origin of the ancestor frame to request configuration from
* @prop {Service[]} [services] -
* Configuration for the annotation services that the client connects to
* @prop {string} [theme]
* Name of the base theme to use.
* @prop {string} [usernameUrl]
* URL template for username links
*/
/**
* The `settings` object used in the sidebar app that is a result of merging
* (filtered and validated) configuration from the host page with configuration
* from h / the browser extension.
*
* @typedef {HostConfig & SidebarConfig} MergedConfig
*/
// Make TypeScript treat this file as a module.
export const unused = {};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment