From bc08b80122e293d4e72cb69c6938b969558aa155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Alby?= Date: Thu, 3 Mar 2022 17:28:03 +0100 Subject: [PATCH] Merge pull request #6899 from overleaf/ta-layout-refactor Refactor Layouts GitOrigin-RevId: 1b963e9240bbb4a43c627c344abd4672e08a7cff --- services/web/app/views/layout-base.pug | 123 +++++++++++++++ services/web/app/views/layout-marketing.pug | 137 ++--------------- services/web/app/views/layout.pug | 140 ++---------------- services/web/app/views/project/editor.pug | 38 +---- .../web/app/views/project/editor/meta.pug | 37 +++++ 5 files changed, 185 insertions(+), 290 deletions(-) create mode 100644 services/web/app/views/layout-base.pug create mode 100644 services/web/app/views/project/editor/meta.pug diff --git a/services/web/app/views/layout-base.pug b/services/web/app/views/layout-base.pug new file mode 100644 index 0000000000..b75855c922 --- /dev/null +++ b/services/web/app/views/layout-base.pug @@ -0,0 +1,123 @@ +doctype html +html( + lang=(currentLngCode || 'en') +) + - metadata = metadata || {} + + block entrypointVar + + block vars + + head + include ./_metadata.pug + + //- Stylesheet + link(rel='stylesheet', href=buildCssPath(getCssThemeModifier(userSettings, brandVariation)), id="main-stylesheet") + block css + each file in entrypointStyles(entrypoint) + link(rel='stylesheet', href=file) + + block _headLinks + + if settings.i18n.subdomainLang + each subdomainDetails in settings.i18n.subdomainLang + if !subdomainDetails.hide + link(rel="alternate", href=subdomainDetails.url+currentUrl, hreflang=subdomainDetails.lngCode) + + //- Scripts + + //- Google Analytics + if (typeof(gaToken) != "undefined") + script(type="text/javascript", nonce=scriptNonce). + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); + script(type="text/javascript", nonce=scriptNonce). + ga('create', '#{gaToken}', '#{settings.cookieDomain.replace(/^\./, "")}'); + ga('set', 'anonymizeIp', true); + ga('send', 'pageview'); + + try { + ga.isBlocked = localStorage.getItem('gaBlocked') === 'true' + if (!ga.isBlocked) { + window.addEventListener('load', function () { + setTimeout(function () { + if (!ga.loaded) localStorage.setItem('gaBlocked', 'true') + }, 4000) + }) + } + } catch (e) {} + else + script(type="text/javascript", nonce=scriptNonce). + window.ga = function() { console.log("would send to GA", arguments) }; + + if (typeof(gaTokenV4) != "undefined") + script(async, nonce=scriptNonce, src='https://www.googletagmanager.com/gtag/js?id=' + gaTokenV4) + script(type="text/javascript", nonce=scriptNonce). + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '#{gaTokenV4}'); + else + script(type = "text/javascript", nonce = scriptNonce). + window.gtag = function() { console.log("would send to GA4", arguments) }; + + block meta + meta(name="ol-csrfToken" content=csrfToken) + //- Configure dynamically loaded assets (via webpack) to be downloaded from CDN + //- See: https://webpack.js.org/guides/public-path/#on-the-fly + meta(name="ol-baseAssetPath" content=buildBaseAssetPath()) + + meta(name="ol-usersEmail" content=getUserEmail()) + meta(name="ol-sharelatex" data-type="json" content={ + siteUrl: settings.siteUrl, + wsUrl, + }) + meta(name="ol-ab" data-type="json" content={}) + meta(name="ol-user_id" content=getLoggedInUserId()) + //- Internationalisation settings + meta(name="ol-i18n" data-type="json" content={ + currentLangCode: currentLngCode + }) + //- Expose some settings globally to the frontend + meta(name="ol-ExposedSettings" data-type="json" content=ExposedSettings) + meta(name="ol-splitTestVariants" data-type="json" content=splitTestVariants || {}) + + if (typeof(settings.algolia) != "undefined") + meta(name="ol-algolia" data-type="json" content={ + appId: settings.algolia.app_id, + apiKey: settings.algolia.read_only_api_key, + indexes: settings.algolia.indexes + }) + + if (typeof(settings.templates) != "undefined") + meta(name="ol-sharelatex.templates" data-type="json" content={ + user_id : settings.templates.user_id, + cdnDomain : settings.templates.cdnDomain, + indexName : settings.templates.indexName + }) + + block head-scripts + + body(ng-csp=(cspEnabled ? "no-unsafe-eval" : false) class=(showThinFooter ? 'thin-footer' : undefined)) + if(settings.recaptcha && settings.recaptcha.siteKeyV3) + script(type="text/javascript", nonce=scriptNonce, src="https://www.recaptcha.net/recaptcha/api.js?render="+settings.recaptcha.siteKeyV3) + + if (typeof(suppressSkipToContent) == "undefined") + a(class="skip-to-content" href="#main-content") #{translate('skip_to_content')} + + block body + + block foot-scripts + each file in entrypointScripts(entrypoint) + script(type="text/javascript", nonce=scriptNonce, src=file) + script(type="text/javascript", nonce=scriptNonce). + //- Look for bundle + var cdnBlocked = typeof Frontend === 'undefined' + //- Prevent loops + var noCdnAlreadyInUrl = window.location.href.indexOf("nocdn=true") != -1 + if (cdnBlocked && !noCdnAlreadyInUrl && navigator.userAgent.indexOf("Googlebot") == -1) { + //- Set query param, server will not set CDN url + window.location.search += "&nocdn=true"; + } diff --git a/services/web/app/views/layout-marketing.pug b/services/web/app/views/layout-marketing.pug index db879cf986..ab5644af7c 100644 --- a/services/web/app/views/layout-marketing.pug +++ b/services/web/app/views/layout-marketing.pug @@ -1,133 +1,20 @@ +extends ./layout-base + include ./_mixins/formMessages -doctype html -html( - lang=(currentLngCode || 'en') -) - - metadata = metadata || {} +block entrypointVar - entrypoint = 'marketing' - //- hook for overriding metadata/page - block vars +block body + if (typeof(suppressNavbar) == "undefined") + include layout/navbar-marketing - head - include ./_metadata.pug + block content - //- Stylesheet - link(rel='stylesheet', href=buildCssPath(getCssThemeModifier(userSettings, brandVariation)), id="main-stylesheet") - block css - each file in entrypointStyles(entrypoint) - link(rel='stylesheet', href=file) - - block _headLinks - - if settings.i18n.subdomainLang - each subdomainDetails in settings.i18n.subdomainLang - if !subdomainDetails.hide - link(rel="alternate", href=subdomainDetails.url+currentUrl, hreflang=subdomainDetails.lngCode) - - //- Scripts - - //- Google Analytics - if (typeof(gaToken) != "undefined") - script(type="text/javascript", nonce=scriptNonce). - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - script(type="text/javascript", nonce=scriptNonce). - ga('create', '#{gaToken}', '#{settings.cookieDomain.replace(/^\./, "")}'); - ga('set', 'anonymizeIp', true); - ga('send', 'pageview'); - - try { - ga.isBlocked = localStorage.getItem('gaBlocked') === 'true' - if (!ga.isBlocked) { - window.addEventListener('load', function () { - setTimeout(function () { - if (!ga.loaded) localStorage.setItem('gaBlocked', 'true') - }, 4000) - }) - } - } catch (e) {} + if (typeof(suppressFooter) == "undefined") + if showThinFooter + include layout/footer-marketing else - script(type="text/javascript", nonce=scriptNonce). - window.ga = function() { console.log("would send to GA", arguments) }; + include layout/fat-footer - if (typeof(gaTokenV4) != "undefined") - script(async, nonce=scriptNonce, src='https://www.googletagmanager.com/gtag/js?id=' + gaTokenV4) - script(type="text/javascript", nonce=scriptNonce). - window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '#{gaTokenV4}'); - - block meta - meta(name="ol-csrfToken" content=csrfToken) - //- Configure dynamically loaded assets (via webpack) to be downloaded from CDN - //- See: https://webpack.js.org/guides/public-path/#on-the-fly - meta(name="ol-baseAssetPath" content=buildBaseAssetPath()) - - meta(name="ol-usersEmail" content=getUserEmail()) - meta(name="ol-sharelatex" data-type="json" content={ - siteUrl: settings.siteUrl, - wsUrl, - }) - meta(name="ol-ab" data-type="json" content={}) - meta(name="ol-user_id" content=getLoggedInUserId()) - //- Internationalisation settings - meta(name="ol-i18n" data-type="json" content={ - currentLangCode: currentLngCode - }) - //- Expose some settings globally to the frontend - meta(name="ol-ExposedSettings" data-type="json" content=ExposedSettings) - - if (typeof(settings.algolia) != "undefined") - meta(name="ol-algolia" data-type="json" content={ - appId: settings.algolia.app_id, - apiKey: settings.algolia.read_only_api_key, - indexes: settings.algolia.indexes - }) - - if (typeof(settings.templates) != "undefined") - meta(name="ol-sharelatex.templates" data-type="json" content={ - user_id : settings.templates.user_id, - cdnDomain : settings.templates.cdnDomain, - indexName : settings.templates.indexName - }) - - block head-scripts - - - body(class=(showThinFooter ? 'thin-footer' : undefined)) - if(settings.recaptcha && settings.recaptcha.siteKeyV3) - script(type="text/javascript", nonce=scriptNonce, src="https://www.recaptcha.net/recaptcha/api.js?render="+settings.recaptcha.siteKeyV3) - - if (typeof(suppressSkipToContent) == "undefined") - a(class="skip-to-content" href="#main-content") #{translate('skip_to_content')} - - if (typeof(suppressNavbar) == "undefined") - include layout/navbar-marketing - - block content - - if (typeof(suppressFooter) == "undefined") - if showThinFooter - include layout/footer-marketing - else - include layout/fat-footer - - != moduleIncludes("contactModal-marketing", locals) - - block foot-scripts - each file in entrypointScripts(entrypoint) - script(type="text/javascript", nonce=scriptNonce, src=file) - script(type="text/javascript", nonce=scriptNonce). - //- Look for bundle - var cdnBlocked = typeof Frontend === 'undefined' - //- Prevent loops - var noCdnAlreadyInUrl = window.location.href.indexOf("nocdn=true") != -1 - if (cdnBlocked && !noCdnAlreadyInUrl && navigator.userAgent.indexOf("Googlebot") == -1) { - //- Set query param, server will not set CDN url - window.location.search += "&nocdn=true"; - } + != moduleIncludes("contactModal-marketing", locals) diff --git a/services/web/app/views/layout.pug b/services/web/app/views/layout.pug index 82fbd1a646..273be77860 100644 --- a/services/web/app/views/layout.pug +++ b/services/web/app/views/layout.pug @@ -1,134 +1,18 @@ +extends ./layout-base -doctype html -html( - lang=(currentLngCode || 'en') -) - - metadata = metadata || {} +block entrypointVar + - entrypoint = 'main' - block vars +block body + if (typeof(suppressNavbar) == "undefined") + include layout/navbar - head - include ./_metadata.pug + block content - //- Stylesheet - link(rel='stylesheet', href=buildCssPath(getCssThemeModifier(userSettings, brandVariation)), id="main-stylesheet") - block css - each file in entrypointStyles('main') - link(rel='stylesheet', href=file) - - block _headLinks - - if settings.i18n.subdomainLang - each subdomainDetails in settings.i18n.subdomainLang - if !subdomainDetails.hide - link(rel="alternate", href=subdomainDetails.url+currentUrl, hreflang=subdomainDetails.lngCode) - - //- Scripts - - //- Google Analytics - if (typeof(gaToken) != "undefined") - script(type="text/javascript", nonce=scriptNonce). - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - script(type="text/javascript", nonce=scriptNonce). - ga('create', '#{gaToken}', '#{settings.cookieDomain.replace(/^\./, "")}'); - ga('set', 'anonymizeIp', true); - ga('send', 'pageview'); - - try { - ga.isBlocked = localStorage.getItem('gaBlocked') === 'true' - if (!ga.isBlocked) { - window.addEventListener('load', function () { - setTimeout(function () { - if (!ga.loaded) localStorage.setItem('gaBlocked', 'true') - }, 4000) - }) - } - } catch (e) {} + if (typeof(suppressFooter) == "undefined") + if showThinFooter + include layout/footer else - script(type="text/javascript", nonce=scriptNonce). - window.ga = function() { console.log("would send to GA", arguments) }; + include layout/fat-footer - if (typeof(gaTokenV4) != "undefined") - script(async, nonce=scriptNonce, src='https://www.googletagmanager.com/gtag/js?id=' + gaTokenV4) - script(type="text/javascript", nonce=scriptNonce). - window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', '#{gaTokenV4}'); - else - script(type = "text/javascript", nonce = scriptNonce). - window.gtag = function() { console.log("would send to GA4", arguments) }; - - block meta - meta(name="ol-csrfToken" content=csrfToken) - //- Configure dynamically loaded assets (via webpack) to be downloaded from CDN - //- See: https://webpack.js.org/guides/public-path/#on-the-fly - meta(name="ol-baseAssetPath" content=buildBaseAssetPath()) - - meta(name="ol-usersEmail" content=getUserEmail()) - meta(name="ol-sharelatex" data-type="json" content={ - siteUrl: settings.siteUrl, - wsUrl, - }) - meta(name="ol-ab" data-type="json" content={}) - meta(name="ol-user_id" content=getLoggedInUserId()) - //- Internationalisation settings - meta(name="ol-i18n" data-type="json" content={ - currentLangCode: currentLngCode - }) - //- Expose some settings globally to the frontend - meta(name="ol-ExposedSettings" data-type="json" content=ExposedSettings) - meta(name="ol-splitTestVariants" data-type="json" content=splitTestVariants || {}) - - if (typeof(settings.algolia) != "undefined") - meta(name="ol-algolia" data-type="json" content={ - appId: settings.algolia.app_id, - apiKey: settings.algolia.read_only_api_key, - indexes: settings.algolia.indexes - }) - - if (typeof(settings.templates) != "undefined") - meta(name="ol-sharelatex.templates" data-type="json" content={ - user_id : settings.templates.user_id, - cdnDomain : settings.templates.cdnDomain, - indexName : settings.templates.indexName - }) - - block head-scripts - - - body(ng-csp=(cspEnabled ? "no-unsafe-eval" : false) class=(showThinFooter ? 'thin-footer' : undefined)) - if(settings.recaptcha && settings.recaptcha.siteKeyV3) - script(type="text/javascript", nonce=scriptNonce, src="https://www.recaptcha.net/recaptcha/api.js?render="+settings.recaptcha.siteKeyV3) - - if (typeof(suppressSkipToContent) == "undefined") - a(class="skip-to-content" href="#main-content") #{translate('skip_to_content')} - - if (typeof(suppressNavbar) == "undefined") - include layout/navbar - - block content - - if (typeof(suppressFooter) == "undefined") - if showThinFooter - include layout/footer - else - include layout/fat-footer - - != moduleIncludes("contactModal", locals) - - block foot-scripts - each file in entrypointScripts("main") - script(type="text/javascript", nonce=scriptNonce, src=file) - script(type="text/javascript", nonce=scriptNonce). - //- Look for bundle - var cdnBlocked = typeof Frontend === 'undefined' - //- Prevent loops - var noCdnAlreadyInUrl = window.location.href.indexOf("nocdn=true") != -1 - if (cdnBlocked && !noCdnAlreadyInUrl && navigator.userAgent.indexOf("Googlebot") == -1) { - //- Set query param, server will not set CDN url - window.location.search += "&nocdn=true"; - } + != moduleIncludes("contactModal", locals) diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index d511884cfb..e9321d9fc3 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -119,43 +119,7 @@ block content .modal-body(ng-bind-html="message") block append meta - meta(name="ol-useV2History" data-type="boolean" content=useV2History) - meta(name="ol-project_id" content=project_id) - meta(name="ol-userSettings" data-type="json" content=userSettings) - meta(name="ol-user" data-type="json" content=user) - meta(name="ol-learnedWords" data-type="json" content=learnedWords) - meta(name="ol-anonymous" data-type="boolean" content=anonymous) - meta(name="ol-brandVariation" data-type="json" content=brandVariation) - meta(name="ol-anonymousAccessToken" content=anonymousAccessToken) - meta(name="ol-isTokenMember" data-type="boolean" content=isTokenMember) - meta(name="ol-isRestrictedTokenMember" data-type="boolean" content=isRestrictedTokenMember) - meta(name="ol-maxDocLength" data-type="json" content=maxDocLength) - meta(name="ol-wikiEnabled" data-type="boolean" content=!!(settings.apis.wiki && settings.apis.wiki.url)) - meta(name="ol-gitBridgePublicBaseUrl" content=gitBridgePublicBaseUrl) - //- Set base path for Ace scripts loaded on demand/workers and don't use cdn - meta(name="ol-aceBasePath" content="/js/" + lib('ace')) - //- Set path for PDFjs CMaps and images - meta(name="ol-pdfCMapsPath" content="/js/cmaps/") - meta(name="ol-pdfImageResourcesPath" content="/images/") - //- enable doc hash checking for all projects - //- used in public/js/libs/sharejs.js - meta(name="ol-useShareJsHash" data-type="boolean" content=true) - meta(name="ol-wsRetryHandshake" data-type="json" content=settings.wsRetryHandshake) - meta(name="ol-logsUIVariant" content=logsUIVariant) - meta(name="ol-showPdfDetach" data-type="boolean" content=showPdfDetach) - meta(name="ol-debugPdfDetach" data-type="boolean" content=debugPdfDetach) - meta(name="ol-showNewPdfPreview" data-type="boolean" content=showNewPdfPreview) - meta(name="ol-showNewSourceEditorOption" data-type="boolean" content=showNewSourceEditorOption) - meta(name="ol-enablePdfCaching" data-type="boolean" content=enablePdfCaching) - meta(name="ol-trackPdfDownload" data-type="boolean" content=trackPdfDownload) - meta(name="ol-resetServiceWorker" data-type="boolean" content=resetServiceWorker) - meta(name="ol-detachRole" data-type="string" content=detachRole) - - - var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {}) - meta(name="ol-fileActionI18n" data-type="json" content=fileActionI18n) - - if (settings.overleaf != null) - meta(name="ol-overallThemes" data-type="json" content=overallThemes) + include ./editor/meta block foot-scripts script(type="text/javascript", nonce=scriptNonce, src=(wsUrl || '/socket.io') + '/socket.io.js') diff --git a/services/web/app/views/project/editor/meta.pug b/services/web/app/views/project/editor/meta.pug new file mode 100644 index 0000000000..01d0eceeac --- /dev/null +++ b/services/web/app/views/project/editor/meta.pug @@ -0,0 +1,37 @@ +meta(name="ol-useV2History" data-type="boolean" content=useV2History) +meta(name="ol-project_id" content=project_id) +meta(name="ol-userSettings" data-type="json" content=userSettings) +meta(name="ol-user" data-type="json" content=user) +meta(name="ol-learnedWords" data-type="json" content=learnedWords) +meta(name="ol-anonymous" data-type="boolean" content=anonymous) +meta(name="ol-brandVariation" data-type="json" content=brandVariation) +meta(name="ol-anonymousAccessToken" content=anonymousAccessToken) +meta(name="ol-isTokenMember" data-type="boolean" content=isTokenMember) +meta(name="ol-isRestrictedTokenMember" data-type="boolean" content=isRestrictedTokenMember) +meta(name="ol-maxDocLength" data-type="json" content=maxDocLength) +meta(name="ol-wikiEnabled" data-type="boolean" content=!!(settings.apis.wiki && settings.apis.wiki.url)) +meta(name="ol-gitBridgePublicBaseUrl" content=gitBridgePublicBaseUrl) +//- Set base path for Ace scripts loaded on demand/workers and don't use cdn +meta(name="ol-aceBasePath" content="/js/" + lib('ace')) +//- Set path for PDFjs CMaps and images +meta(name="ol-pdfCMapsPath" content="/js/cmaps/") +meta(name="ol-pdfImageResourcesPath" content="/images/") +//- enable doc hash checking for all projects +//- used in public/js/libs/sharejs.js +meta(name="ol-useShareJsHash" data-type="boolean" content=true) +meta(name="ol-wsRetryHandshake" data-type="json" content=settings.wsRetryHandshake) +meta(name="ol-logsUIVariant" content=logsUIVariant) +meta(name="ol-showPdfDetach" data-type="boolean" content=showPdfDetach) +meta(name="ol-debugPdfDetach" data-type="boolean" content=debugPdfDetach) +meta(name="ol-showNewPdfPreview" data-type="boolean" content=showNewPdfPreview) +meta(name="ol-showNewSourceEditorOption" data-type="boolean" content=showNewSourceEditorOption) +meta(name="ol-enablePdfCaching" data-type="boolean" content=enablePdfCaching) +meta(name="ol-trackPdfDownload" data-type="boolean" content=trackPdfDownload) +meta(name="ol-resetServiceWorker" data-type="boolean" content=resetServiceWorker) +meta(name="ol-detachRole" data-type="string" content=detachRole) + +- var fileActionI18n = ['edited', 'renamed', 'created', 'deleted'].reduce((acc, i) => {acc[i] = translate('file_action_' + i); return acc}, {}) +meta(name="ol-fileActionI18n" data-type="json" content=fileActionI18n) + +if (settings.overleaf != null) + meta(name="ol-overallThemes" data-type="json" content=overallThemes)