mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add new fat footer (#6260)
GitOrigin-RevId: 64c50caac2ec8d56b3f49d6f97c8a1c4d4b3a496
This commit is contained in:
parent
cdf88358d4
commit
4610734f07
14 changed files with 417 additions and 64 deletions
|
@ -613,6 +613,7 @@ const ProjectController = {
|
|||
zipFileSizeLimit: Settings.maxUploadSize,
|
||||
isOverleaf: !!Settings.overleaf,
|
||||
metadata: { viewport: false },
|
||||
showThinFooter: true, // don't show the fat footer on the projects dashboard, as there's a fixed space available
|
||||
}
|
||||
|
||||
const paidUser =
|
||||
|
|
|
@ -355,6 +355,11 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
|
|||
next()
|
||||
})
|
||||
|
||||
webRouter.use(function (req, res, next) {
|
||||
res.locals.showThinFooter = !Features.hasFeature('saas')
|
||||
next()
|
||||
})
|
||||
|
||||
webRouter.use(function (req, res, next) {
|
||||
res.locals.ExposedSettings = {
|
||||
isOverleaf: Settings.overleaf != null,
|
||||
|
|
|
@ -99,7 +99,7 @@ html(
|
|||
block head-scripts
|
||||
|
||||
|
||||
body
|
||||
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)
|
||||
|
||||
|
@ -112,7 +112,10 @@ html(
|
|||
block content
|
||||
|
||||
if (typeof(suppressFooter) == "undefined")
|
||||
include layout/footer-marketing
|
||||
if showThinFooter
|
||||
include layout/footer-marketing
|
||||
else
|
||||
include layout/fat-footer
|
||||
|
||||
!= moduleIncludes("contactModal-marketing", locals)
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ html(
|
|||
block head-scripts
|
||||
|
||||
|
||||
body(ng-csp=(cspEnabled ? "no-unsafe-eval" : false))
|
||||
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)
|
||||
|
||||
|
@ -113,7 +113,10 @@ html(
|
|||
block content
|
||||
|
||||
if (typeof(suppressFooter) == "undefined")
|
||||
include layout/footer
|
||||
if showThinFooter
|
||||
include layout/footer
|
||||
else
|
||||
include layout/fat-footer
|
||||
|
||||
!= moduleIncludes("contactModal", locals)
|
||||
|
||||
|
|
18
services/web/app/views/layout/fat-footer-base.pug
Normal file
18
services/web/app/views/layout/fat-footer-base.pug
Normal file
|
@ -0,0 +1,18 @@
|
|||
.fat-footer-base
|
||||
.fat-footer-base-section.fat-footer-base-meta
|
||||
.fat-footer-base-item
|
||||
.fat-footer-base-copyright © #{new Date().getFullYear()} Overleaf
|
||||
a(href="/legal") #{translate('privacy_and_terms')}
|
||||
ul.fat-footer-base-item.list-unstyled.fat-footer-base-language
|
||||
include language-picker
|
||||
.fat-footer-base-section.fat-footer-base-social
|
||||
.fat-footer-base-item
|
||||
a.fat-footer-social(href="https://twitter.com/overleaf")
|
||||
i.fa.fa-twitter-square(aria-hidden="true")
|
||||
.sr-only Overleaf on Twitter
|
||||
a.fat-footer-social(href="https://www.facebook.com/overleaf.editor")
|
||||
i.fa.fa-facebook-square(aria-hidden="true")
|
||||
.sr-only Overleaf on Facebook
|
||||
a.fat-footer-social(href="https://www.linkedin.com/company/writelatex-limited")
|
||||
i.fa.fa-linkedin-square(aria-hidden="true")
|
||||
.sr-only Overleaf on LinkedIn
|
79
services/web/app/views/layout/fat-footer.pug
Normal file
79
services/web/app/views/layout/fat-footer.pug
Normal file
|
@ -0,0 +1,79 @@
|
|||
footer.fat-footer.hidden-print
|
||||
.fat-footer-container
|
||||
.fat-footer-sections(class=hideFatFooter ? 'hidden' : undefined)
|
||||
.footer-section#footer-brand
|
||||
a(href='/', aria-label=settings.appName).footer-brand
|
||||
|
||||
.footer-section
|
||||
.footer-section-heading #{translate('About')}
|
||||
|
||||
ul.list-unstyled
|
||||
li
|
||||
a(href="/about") #{translate('footer_about_us')}
|
||||
li
|
||||
a(href="/about/values") #{translate('our_values')}
|
||||
li
|
||||
a(href="https://apply.workable.com/overleaf/") #{translate('careers')}
|
||||
li
|
||||
a(href="/for/press") #{translate('press_and_awards')}
|
||||
li
|
||||
a(href="/blog") #{translate('blog')}
|
||||
|
||||
.footer-section
|
||||
.footer-section-heading #{translate('learn')}
|
||||
|
||||
ul.list-unstyled
|
||||
li
|
||||
a(href="/learn/latex/Learn_LaTeX_in_30_minutes") #{translate('latex_in_thirty_minutes')}
|
||||
li
|
||||
a(href="/latex/templates") #{translate('templates')}
|
||||
li
|
||||
a(href="/events/webinars") #{translate('webinars')}
|
||||
li
|
||||
a(href="/learn/latex/Tutorials") #{translate('tutorials')}
|
||||
li
|
||||
a(href="/learn/latex/Inserting_Images") #{translate('how_to_insert_images')}
|
||||
li
|
||||
a(href="/learn/latex/Tables") #{translate('how_to_create_tables')}
|
||||
|
||||
.footer-section
|
||||
.footer-section-heading #{translate('footer_plans_and_pricing')}
|
||||
|
||||
ul.list-unstyled
|
||||
li
|
||||
a(href="/learn/how-to/Overleaf_premium_features") #{translate('premium_features')}
|
||||
li
|
||||
a(href="/user/subscription/plans") #{translate('for_individuals_and_groups')}
|
||||
li
|
||||
a(href="/for/enterprises") #{translate('for_enterprise')}
|
||||
li
|
||||
a(href="/for/universities") #{translate('for_universities')}
|
||||
li
|
||||
a(href="/user/subscription/plans#view=student") #{translate('for_students')}
|
||||
|
||||
.footer-section
|
||||
.footer-section-heading #{translate('get_involved')}
|
||||
|
||||
ul.list-unstyled
|
||||
li
|
||||
a(href="/for/community/advisors") #{translate('become_an_advisor')}
|
||||
li
|
||||
a(href="https://calendly.com/overleaf/user-research") #{translate('participate_in_user_research')}
|
||||
if user
|
||||
li
|
||||
a(href="/beta/participate") #{translate('join_beta_program')}
|
||||
li
|
||||
a(href="/user/bonus") #{translate('refer_a_friend')}
|
||||
|
||||
.footer-section
|
||||
.footer-section-heading #{translate('help')}
|
||||
|
||||
ul.list-unstyled
|
||||
li
|
||||
a(href="/learn") #{translate('Documentation')}
|
||||
li
|
||||
a(href="/contact") #{translate('footer_contact_us')}
|
||||
li
|
||||
a(href="https://status.overleaf.com/") #{translate('website_status')}
|
||||
|
||||
include fat-footer-base
|
|
@ -17,27 +17,7 @@ footer.site-footer
|
|||
strong.text-muted |
|
||||
|
||||
if showLanguagePicker
|
||||
li.dropdown.dropup.subdued
|
||||
a.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false",
|
||||
aria-label="Select " + translate('language'),
|
||||
data-ol-lang-selector-tooltip,
|
||||
title=translate('language')
|
||||
)
|
||||
i.fa.fa-fw.fa-language
|
||||
|
|
||||
| #{settings.translatedLanguages[currentLngCode]}
|
||||
|
||||
ul.dropdown-menu(role="menu")
|
||||
li.dropdown-header #{translate("language")}
|
||||
each subdomainDetails, subdomain in settings.i18n.subdomainLang
|
||||
if !subdomainDetails.hide
|
||||
li.lngOption
|
||||
a.menu-indent(href=subdomainDetails.url+currentUrlWithQueryParams)
|
||||
| #{settings.translatedLanguages[subdomainDetails.lngCode]}
|
||||
include language-picker
|
||||
|
||||
if showLanguagePicker && hasCustomLeftNav
|
||||
li
|
||||
|
@ -51,7 +31,6 @@ footer.site-footer
|
|||
| !{item.text}
|
||||
|
||||
ul.col-md-3.text-right
|
||||
|
||||
each item in nav.right_footer
|
||||
li(ng-non-bindable)
|
||||
if item.url
|
||||
|
|
|
@ -6,10 +6,9 @@ footer.site-footer
|
|||
.site-footer-content.hidden-print
|
||||
.row
|
||||
ul.col-md-9
|
||||
if hasFeature('saas')
|
||||
li © #{new Date().getFullYear()} Overleaf
|
||||
else if !settings.nav.hide_powered_by
|
||||
if !settings.nav.hide_powered_by
|
||||
li
|
||||
//- year of Server Pro release, static
|
||||
| © 2021
|
||||
|
|
||||
a(href='https://www.overleaf.com/for/enterprises') Powered by Overleaf
|
||||
|
@ -19,27 +18,7 @@ footer.site-footer
|
|||
strong.text-muted |
|
||||
|
||||
if showLanguagePicker
|
||||
li.dropdown.dropup.subdued(dropdown)
|
||||
a.dropdown-toggle(
|
||||
href="#",
|
||||
dropdown-toggle,
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false",
|
||||
aria-label="Select " + translate('language')
|
||||
tooltip=translate('language')
|
||||
)
|
||||
i.fa.fa-fw.fa-language
|
||||
|
|
||||
| #{settings.translatedLanguages[currentLngCode]}
|
||||
|
||||
ul.dropdown-menu
|
||||
li.dropdown-header #{translate("language")}
|
||||
each subdomainDetails, subdomain in settings.i18n.subdomainLang
|
||||
if !subdomainDetails.hide
|
||||
li.lngOption
|
||||
a.menu-indent(href=subdomainDetails.url+currentUrlWithQueryParams)
|
||||
| #{settings.translatedLanguages[subdomainDetails.lngCode]}
|
||||
include language-picker
|
||||
|
||||
if showLanguagePicker && hasCustomLeftNav
|
||||
li
|
||||
|
|
23
services/web/app/views/layout/language-picker.pug
Normal file
23
services/web/app/views/layout/language-picker.pug
Normal file
|
@ -0,0 +1,23 @@
|
|||
li.dropdown.dropup.subdued(dropdown).language-picker
|
||||
a.dropdown-toggle#language-picker-toggle(
|
||||
href="#",
|
||||
dropdown-toggle,
|
||||
data-ol-lang-selector-tooltip,
|
||||
data-toggle="dropdown",
|
||||
role="button"
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false",
|
||||
aria-label="Select " + translate('language'),
|
||||
tooltip=translate('language')
|
||||
)
|
||||
i.fa.fa-fw.fa-language
|
||||
|
|
||||
| #{settings.translatedLanguages[currentLngCode]}
|
||||
|
||||
ul.dropdown-menu(role="menu" aria-labelledby="language-picker-toggle")
|
||||
li.dropdown-header #{translate("language")}
|
||||
each subdomainDetails, subdomain in settings.i18n.subdomainLang
|
||||
if !subdomainDetails.hide
|
||||
li.lngOption
|
||||
a.menu-indent(href=subdomainDetails.url+currentUrlWithQueryParams role="menuitem")
|
||||
| #{settings.translatedLanguages[subdomainDetails.lngCode]}
|
|
@ -7,24 +7,28 @@ import getMeta from '../../../utils/meta'
|
|||
let currentView = 'monthly'
|
||||
let currentCurrencyCode = getMeta('ol-recommendedCurrency')
|
||||
|
||||
function selectView(view) {
|
||||
document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
|
||||
if (el.getAttribute('data-ol-view-tab') === view) {
|
||||
el.classList.add('active')
|
||||
} else {
|
||||
el.classList.remove('active')
|
||||
}
|
||||
})
|
||||
document.querySelectorAll('[data-ol-view]').forEach(el => {
|
||||
el.hidden = el.getAttribute('data-ol-view') !== view
|
||||
})
|
||||
currentView = view
|
||||
updateLinkTargets()
|
||||
}
|
||||
|
||||
function setUpViewSwitching(liEl) {
|
||||
const view = liEl.getAttribute('data-ol-view-tab')
|
||||
liEl.querySelector('a').addEventListener('click', function (e) {
|
||||
e.preventDefault()
|
||||
eventTracking.send('subscription-funnel', 'plans-page', `${view}-prices`) // deprecated by plans-page-toggle
|
||||
eventTracking.send('subscription-funnel', 'plans-page', `${view}-prices`)
|
||||
eventTracking.sendMB('plans-page-toggle', { button: view })
|
||||
document.querySelectorAll('[data-ol-view-tab]').forEach(el => {
|
||||
if (el.getAttribute('data-ol-view-tab') === view) {
|
||||
el.classList.add('active')
|
||||
} else {
|
||||
el.classList.remove('active')
|
||||
}
|
||||
})
|
||||
document.querySelectorAll('[data-ol-view]').forEach(el => {
|
||||
el.hidden = el.getAttribute('data-ol-view') !== view
|
||||
})
|
||||
currentView = view
|
||||
updateLinkTargets()
|
||||
selectView(view)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,6 +81,23 @@ function updateLinkTargets() {
|
|||
})
|
||||
}
|
||||
|
||||
function selectViewFromHash() {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.hash.substring(1))
|
||||
const view = params.get('view')
|
||||
if (view) {
|
||||
// make sure the selected view is valid
|
||||
if (document.querySelector(`[data-ol-view-tab="${view}"]`)) {
|
||||
selectView(view)
|
||||
// clear the hash so it doesn't persist when switching plans
|
||||
window.location.hash = ''
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('[data-ol-view-tab]').forEach(setUpViewSwitching)
|
||||
document
|
||||
.querySelectorAll('[data-ol-currencyCode-switch]')
|
||||
|
@ -85,3 +106,6 @@ document
|
|||
.querySelectorAll('[data-ol-start-new-subscription]')
|
||||
.forEach(setUpSubscriptionTracking)
|
||||
updateLinkTargets()
|
||||
|
||||
selectViewFromHash()
|
||||
window.addEventListener('hashchange', selectViewFromHash)
|
||||
|
|
|
@ -50,3 +50,215 @@ footer.site-footer {
|
|||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.fat-footer {
|
||||
background: @ol-blue-gray-6;
|
||||
color: @ol-blue-gray-1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.fat-footer-container {
|
||||
margin: @margin-xxl auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @ol-blue-gray-1;
|
||||
}
|
||||
|
||||
.footer-brand-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.fat-footer-sections {
|
||||
display: grid;
|
||||
column-gap: @margin-md;
|
||||
padding: 0 @padding-md @padding-md;
|
||||
}
|
||||
|
||||
.footer-brand {
|
||||
display: block;
|
||||
height: 37px; /* TODO: configurable? */
|
||||
width: @navbar-brand-width;
|
||||
background-image: @navbar-brand-image-url;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
.footer-section-heading {
|
||||
font-family: @font-family-serif;
|
||||
font-size: @font-size-h3;
|
||||
line-height: @headings-line-height;
|
||||
margin-bottom: @margin-md;
|
||||
margin-top: @margin-md;
|
||||
}
|
||||
|
||||
.footer-section ul {
|
||||
font-family: @font-family-sans-serif;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-small;
|
||||
}
|
||||
|
||||
.footer-section li {
|
||||
padding-bottom: @padding-sm;
|
||||
}
|
||||
|
||||
#footer-brand {
|
||||
grid-column: ~'1/-1';
|
||||
margin-top: @margin-md;
|
||||
}
|
||||
|
||||
.fat-footer-base {
|
||||
color: @ol-blue-gray-2;
|
||||
font-size: @font-size-small;
|
||||
line-height: @line-height-base;
|
||||
|
||||
.fat-footer-base-meta a:not(.dropdown-toggle) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.language-picker .dropdown-menu {
|
||||
.dropdown-header {
|
||||
display: none; /* hiding rather than removing as still needed in the thin footer */
|
||||
}
|
||||
|
||||
a {
|
||||
color: @gray-dark;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fat-footer-base-item {
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.fat-footer-sections {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(4, auto);
|
||||
}
|
||||
|
||||
.fat-footer-base {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: @margin-md auto 0;
|
||||
|
||||
.fat-footer-base-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fat-footer-base-social {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.fat-footer-base-meta {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
align-items: center;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.fat-footer-base-item {
|
||||
padding: @padding-xs;
|
||||
margin: @margin-lg / 2;
|
||||
}
|
||||
|
||||
.fat-footer-base-meta .fat-footer-base-item {
|
||||
gap: @margin-lg;
|
||||
}
|
||||
|
||||
.fat-footer-base-social .fat-footer-base-item {
|
||||
gap: @margin-md;
|
||||
}
|
||||
|
||||
.fat-footer-social {
|
||||
font-size: @fat-footer-social-font-size;
|
||||
}
|
||||
|
||||
.fat-footer-base-copyright {
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
.fat-footer-container {
|
||||
width: (@screen-sm - (@padding-sm * 2));
|
||||
}
|
||||
|
||||
#footer-brand {
|
||||
grid-column: auto;
|
||||
grid-row: ~'1/-1';
|
||||
}
|
||||
|
||||
.fat-footer-sections {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-rows: repeat(2, auto);
|
||||
}
|
||||
|
||||
.footer-section:last-of-type {
|
||||
grid-column: 4;
|
||||
}
|
||||
|
||||
.footer-section ul {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.fat-footer-base {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: @margin-md auto;
|
||||
|
||||
.fat-footer-base-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fat-footer-base-item {
|
||||
padding: @padding-xs;
|
||||
margin: @margin-xs;
|
||||
}
|
||||
|
||||
.fat-footer-base-meta .fat-footer-base-item {
|
||||
gap: @margin-md;
|
||||
}
|
||||
|
||||
.fat-footer-social {
|
||||
margin: 0 @margin-xs;
|
||||
font-size: @fat-footer-social-font-size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-md-min) {
|
||||
.fat-footer-container {
|
||||
width: (@screen-md - @padding-md);
|
||||
}
|
||||
|
||||
.fat-footer-sections {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-lg-min) {
|
||||
.fat-footer-container {
|
||||
width: (@screen-lg - @padding-lg);
|
||||
}
|
||||
|
||||
.fat-footer-sections {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
grid-template-rows: auto;
|
||||
}
|
||||
|
||||
.footer-section:last-of-type {
|
||||
grid-column: 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,11 +31,14 @@ body {
|
|||
background-color: @body-bg;
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
padding-bottom: @footer-height;
|
||||
& > .content {
|
||||
min-height: calc(~'100vh -' @footer-height);
|
||||
padding-top: @header-height + @content-margin-vertical;
|
||||
}
|
||||
|
||||
.thin-footer {
|
||||
padding-bottom: @footer-height;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset fonts for relevant elements
|
||||
|
|
|
@ -969,6 +969,7 @@
|
|||
@footer-link-hover-color: @link-hover-color-alt;
|
||||
@footer-bg-color: #fff;
|
||||
@footer-padding: 2em 0;
|
||||
@fat-footer-social-font-size: 30px;
|
||||
|
||||
// Editor header
|
||||
@ide-body-top-offset: 40px;
|
||||
|
|
|
@ -832,6 +832,29 @@
|
|||
"Terms": "Terms",
|
||||
"Security": "Security",
|
||||
"About": "About",
|
||||
"learn": "Learn",
|
||||
"latex_in_thirty_minutes": "LaTeX in 30 minutes",
|
||||
"how_to_insert_images": "How to insert images",
|
||||
"how_to_create_tables": "How to create tables",
|
||||
"for_individuals_and_groups": "For individuals & groups",
|
||||
"for_enterprise": "For enterprise",
|
||||
"for_universities": "For universities",
|
||||
"for_students": "For students",
|
||||
"get_involved": "Get involved",
|
||||
"become_an_advisor": "Become an __appName__ advisor",
|
||||
"participate_in_user_research": "Participate in user research",
|
||||
"join_beta_program": "Join beta program",
|
||||
"refer_a_friend": "Refer a friend",
|
||||
"webinars": "Webinars",
|
||||
"tutorials": "Tutorials",
|
||||
"footer_plans_and_pricing": "Plans & pricing",
|
||||
"footer_contact_us": "Contact us",
|
||||
"website_status": "Website status",
|
||||
"privacy_and_terms": "Privacy and Terms",
|
||||
"footer_about_us": "About us",
|
||||
"our_values": "Our values",
|
||||
"careers": "Careers",
|
||||
"press_and_awards": "Press & awards",
|
||||
"editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.",
|
||||
"word_count": "Word Count",
|
||||
"please_compile_pdf_before_word_count": "Please compile your project before performing a word count",
|
||||
|
|
Loading…
Reference in a new issue