meta.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import { User, Features } from '../../../types/user'
  2. import { User as MinimalUser } from '../../../types/admin/user'
  3. import { User as ManagedUser } from '../../../types/group-management/user'
  4. import { UserSettings } from '../../../types/user-settings'
  5. import { OAuthProviders } from '../../../types/oauth-providers'
  6. import { ExposedSettings } from '../../../types/exposed-settings'
  7. import {
  8. type AllowedImageName,
  9. OverallThemeMeta,
  10. type SpellCheckLanguage,
  11. } from '../../../types/project-settings'
  12. import { CurrencyCode } from '../../../types/subscription/currency'
  13. import { PricingFormState } from '../../../types/subscription/payment-context-value'
  14. import { Plan } from '../../../types/subscription/plan'
  15. import { Affiliation } from '../../../types/affiliation'
  16. import type { PortalTemplate } from '../../../types/portal-template'
  17. import { UserEmailData } from '../../../types/user-email'
  18. import {
  19. GroupsAndEnterpriseBannerVariant,
  20. Institution as InstitutionType,
  21. Notification as NotificationType,
  22. PendingGroupSubscriptionEnrollment,
  23. } from '../../../types/project/dashboard/notification'
  24. import { Survey } from '../../../types/project/dashboard/survey'
  25. import { GetProjectsResponseBody } from '../../../types/project/dashboard/api'
  26. import { Tag } from '../../../app/src/Features/Tags/types'
  27. import { Institution } from '../../../types/institution'
  28. import {
  29. ManagedGroupSubscription,
  30. MemberGroupSubscription,
  31. } from '../../../types/subscription/dashboard/subscription'
  32. import { SplitTestInfo } from '../../../types/split-test'
  33. import { ValidationStatus } from '../../../types/group-management/validation'
  34. import { ManagedInstitution } from '../../../types/subscription/dashboard/managed-institution'
  35. import { GroupSSOTestResult } from '../../../modules/group-settings/frontend/js/utils/types'
  36. import {
  37. AccessToken,
  38. InstitutionLink,
  39. SAMLError,
  40. } from '../../../types/settings-page'
  41. import { SuggestedLanguage } from '../../../types/system-message'
  42. import type { TeamInvite } from '../../../types/team-invite'
  43. import { GroupPlans } from '../../../types/subscription/dashboard/group-plans'
  44. import { GroupSSOLinkingStatus } from '../../../types/subscription/sso'
  45. import { PasswordStrengthOptions } from '../../../types/password-strength-options'
  46. import { Subscription as ProjectDashboardSubscription } from '../../../types/project/dashboard/subscription'
  47. import { ThirdPartyIds } from '../../../types/third-party-ids'
  48. import { Publisher } from '../../../types/subscription/dashboard/publisher'
  49. import _ from 'lodash'
  50. import { isSplitTestEnabled } from '@/utils/splitTestUtils'
  51. export interface Meta {
  52. 'ol-ExposedSettings': ExposedSettings
  53. 'ol-allInReconfirmNotificationPeriods': UserEmailData[]
  54. 'ol-allowedExperiments': string[]
  55. 'ol-allowedImageNames': AllowedImageName[]
  56. 'ol-anonymous': boolean
  57. 'ol-bootstrapVersion': 3 | 5
  58. 'ol-brandVariation': Record<string, any>
  59. // dynamic keys based on permissions
  60. 'ol-cannot-add-secondary-email': boolean
  61. 'ol-cannot-change-password': boolean
  62. 'ol-cannot-delete-own-account': boolean
  63. 'ol-cannot-join-subscription': boolean
  64. 'ol-cannot-leave-group-subscription': boolean
  65. 'ol-cannot-link-google-sso': boolean
  66. 'ol-cannot-link-other-third-party-sso': boolean
  67. 'ol-cannot-reactivate-subscription': boolean
  68. 'ol-cannot-use-ai': boolean
  69. 'ol-countryCode': PricingFormState['country']
  70. 'ol-couponCode': PricingFormState['coupon']
  71. 'ol-createdAt': Date
  72. 'ol-csrfToken': string
  73. 'ol-currentInstitutionsWithLicence': Institution[]
  74. 'ol-currentManagedUserAdminEmail': string
  75. 'ol-currentUrl': string
  76. 'ol-debugPdfDetach': boolean
  77. 'ol-detachRole': 'detached' | 'detacher' | ''
  78. 'ol-dropbox': { error: boolean; registered: boolean }
  79. 'ol-editorThemes': string[]
  80. 'ol-email': string
  81. 'ol-emailAddressLimit': number
  82. 'ol-error': { name: string } | undefined
  83. 'ol-expired': boolean
  84. 'ol-features': Features
  85. 'ol-fromPlansPage': boolean
  86. 'ol-gitBridgeEnabled': boolean
  87. 'ol-gitBridgePublicBaseUrl': string
  88. 'ol-github': { enabled: boolean; error: boolean }
  89. 'ol-groupId': string
  90. 'ol-groupName': string
  91. 'ol-groupPlans': GroupPlans
  92. 'ol-groupSSOActive': boolean
  93. 'ol-groupSSOTestResult': GroupSSOTestResult
  94. 'ol-groupSettingsEnabledFor': string[]
  95. 'ol-groupSize': number
  96. 'ol-groupSsoSetupSuccess': boolean
  97. 'ol-groupSubscriptionsPendingEnrollment': PendingGroupSubscriptionEnrollment[]
  98. 'ol-groupsAndEnterpriseBannerVariant': GroupsAndEnterpriseBannerVariant
  99. 'ol-hasGroupSSOFeature': boolean
  100. 'ol-hasIndividualRecurlySubscription': boolean
  101. 'ol-hasManagedUsersFeature': boolean
  102. 'ol-hasPassword': boolean
  103. 'ol-hasSubscription': boolean
  104. 'ol-hasTrackChangesFeature': boolean
  105. 'ol-hideLinkingWidgets': boolean // CI only
  106. 'ol-i18n': { currentLangCode: string }
  107. 'ol-inactiveTutorials': string[]
  108. 'ol-institutionEmailNonCanonical': string | undefined
  109. 'ol-institutionLinked': InstitutionLink | undefined
  110. 'ol-inviteToken': string
  111. 'ol-inviterName': string
  112. 'ol-isExternalAuthenticationSystemUsed': boolean
  113. 'ol-isManagedAccount': boolean
  114. 'ol-isProfessional': boolean
  115. 'ol-isRegisteredViaGoogle': boolean
  116. 'ol-isRestrictedTokenMember': boolean
  117. 'ol-isSaas': boolean
  118. 'ol-itm_campaign': string
  119. 'ol-itm_content': string
  120. 'ol-itm_referrer': string
  121. 'ol-labs': boolean
  122. 'ol-languages': SpellCheckLanguage[]
  123. 'ol-learnedWords': string[]
  124. 'ol-legacyEditorThemes': string[]
  125. 'ol-linkSharingWarning': boolean
  126. 'ol-loadingText': string
  127. 'ol-managedGroupSubscriptions': ManagedGroupSubscription[]
  128. 'ol-managedInstitutions': ManagedInstitution[]
  129. 'ol-managedPublishers': Publisher[]
  130. 'ol-managedUsersActive': boolean
  131. 'ol-managedUsersEnabled': boolean
  132. 'ol-managers': MinimalUser[]
  133. 'ol-mathJaxPath': string
  134. 'ol-maxDocLength': number
  135. 'ol-memberGroupSubscriptions': MemberGroupSubscription[]
  136. 'ol-memberOfSSOEnabledGroups': GroupSSOLinkingStatus[]
  137. 'ol-members': MinimalUser[]
  138. 'ol-no-single-dollar': boolean
  139. 'ol-notifications': NotificationType[]
  140. 'ol-notificationsInstitution': InstitutionType[]
  141. 'ol-oauthProviders': OAuthProviders
  142. 'ol-optionalPersonalAccessToken': boolean
  143. 'ol-overallThemes': OverallThemeMeta[]
  144. 'ol-passwordStrengthOptions': PasswordStrengthOptions
  145. 'ol-personalAccessTokens': AccessToken[] | undefined
  146. 'ol-plan': Plan
  147. 'ol-planCode': string
  148. 'ol-planCodesChangingAtTermEnd': string[] | undefined
  149. 'ol-plans': Plan[]
  150. 'ol-portalTemplates': PortalTemplate[]
  151. 'ol-postCheckoutRedirect': string
  152. 'ol-postUrl': string
  153. 'ol-prefetchedProjectsBlob': GetProjectsResponseBody | undefined
  154. 'ol-primaryEmail': { email: string; confirmed: boolean }
  155. 'ol-project': any // TODO
  156. 'ol-projectSyncSuccessMessage': string
  157. 'ol-projectTags': Tag[]
  158. 'ol-project_id': string
  159. 'ol-recommendedCurrency': CurrencyCode
  160. 'ol-reconfirmationRemoveEmail': string
  161. 'ol-reconfirmedViaSAML': string
  162. 'ol-recurlyApiKey': string
  163. 'ol-recurlySubdomain': string
  164. 'ol-samlError': SAMLError | undefined
  165. 'ol-settingsGroupSSO': { enabled: boolean } | undefined
  166. 'ol-settingsPlans': Plan[]
  167. 'ol-shouldAllowEditingDetails': boolean
  168. 'ol-showAiErrorAssistant': boolean
  169. 'ol-showBrlGeoBanner': boolean
  170. 'ol-showCouponField': boolean
  171. 'ol-showGroupsAndEnterpriseBanner': boolean
  172. 'ol-showInrGeoBanner': boolean
  173. 'ol-showLATAMBanner': boolean
  174. 'ol-showPersonalAccessToken': boolean
  175. 'ol-showSupport': boolean
  176. 'ol-showSymbolPalette': boolean
  177. 'ol-showTemplatesServerPro': boolean
  178. 'ol-showUpgradePrompt': boolean
  179. 'ol-skipUrl': string
  180. 'ol-splitTestInfo': { [name: string]: SplitTestInfo }
  181. 'ol-splitTestVariants': { [name: string]: string }
  182. 'ol-ssoDisabled': boolean
  183. 'ol-ssoErrorMessage': string
  184. 'ol-subscription': any // TODO: mixed types, split into two fields
  185. 'ol-subscriptionId': string
  186. 'ol-suggestedLanguage': SuggestedLanguage | undefined
  187. 'ol-survey': Survey | undefined
  188. 'ol-symbolPaletteAvailable': boolean
  189. 'ol-tags': Tag[]
  190. 'ol-teamInvites': TeamInvite[]
  191. 'ol-thirdPartyIds': ThirdPartyIds
  192. 'ol-translationIoNotLoaded': string
  193. 'ol-translationLoadErrorMessage': string
  194. 'ol-translationMaintenance': string
  195. 'ol-translationUnableToJoin': string
  196. 'ol-useShareJsHash': boolean
  197. 'ol-user': User
  198. 'ol-userAffiliations': Affiliation[]
  199. 'ol-userEmails': UserEmailData[]
  200. 'ol-userSettings': UserSettings
  201. 'ol-user_id': string | undefined
  202. 'ol-users': ManagedUser[]
  203. 'ol-usersBestSubscription': ProjectDashboardSubscription | undefined
  204. 'ol-usersEmail': string | undefined
  205. 'ol-validationStatus': ValidationStatus
  206. 'ol-wikiEnabled': boolean
  207. 'ol-writefullCssUrl': string
  208. 'ol-writefullEnabled': boolean
  209. 'ol-writefullJsUrl': string
  210. 'ol-wsUrl': string
  211. }
  212. // cache for parsed values
  213. window.metaAttributesCache = window.metaAttributesCache || new Map()
  214. export default function getMeta<T extends keyof Meta>(name: T): Meta[T] {
  215. if (window.metaAttributesCache.has(name)) {
  216. return window.metaAttributesCache.get(name)
  217. }
  218. const element = document.head.querySelector(
  219. `meta[name="${name}"]`
  220. ) as HTMLMetaElement
  221. if (!element) {
  222. return undefined!
  223. }
  224. const plainTextValue = element.content
  225. let value
  226. switch (element.dataset.type) {
  227. case 'boolean':
  228. // in pug: content=false -> no content field
  229. // in pug: content=true -> empty content field
  230. value = element.hasAttribute('content')
  231. break
  232. case 'json':
  233. if (!plainTextValue) {
  234. // JSON.parse('') throws
  235. value = undefined
  236. } else {
  237. value = JSON.parse(plainTextValue)
  238. }
  239. break
  240. default:
  241. value = plainTextValue
  242. }
  243. window.metaAttributesCache.set(name, value)
  244. return value
  245. }
  246. function convertMetaToWindowAttributes() {
  247. Array.from(document.querySelectorAll('meta[name^="ol-"]'))
  248. .map(element => (element as HTMLMetaElement).name)
  249. // process short labels before long ones:
  250. // e.g. assign 'foo' before 'foo.bar'
  251. .sort()
  252. .forEach(nameWithNamespace => {
  253. const label = nameWithNamespace.slice('ol-'.length)
  254. // @ts-ignore
  255. _.set(window, label, getMeta(nameWithNamespace))
  256. })
  257. }
  258. // Deduplicate warning, the bootstrap-3 bundle ships its own copy of this module.
  259. if (!window.warnedAboutWindowAttributeRemoval) {
  260. window.warnedAboutWindowAttributeRemoval = true
  261. // Notify any extension developers about the upcoming removal of window attributes.
  262. // eslint-disable-next-line no-console
  263. console.warn(
  264. 'overleaf.com: We are sunsetting window properties like "window.project_id". If you need access to any of these, please reach out to support@overleaf.com to discuss options.'
  265. )
  266. }
  267. if (!isSplitTestEnabled('remove-window-attributes')) {
  268. convertMetaToWindowAttributes()
  269. }