Просмотр исходного кода

Merge pull request #1543 from sharelatex/as-fix-potential-angular-xss

Fix potential Angular XSS issues

GitOrigin-RevId: a18a609a25b29e910cb78e28a37398417cfe4842
Alasdair Smith 7 лет назад
Родитель
Сommit
41f75b5936
29 измененных файлов с 110 добавлено и 127 удалено
  1. 1 1
      services/web/app/views/_mixins/faq_search.pug
  2. 13 13
      services/web/app/views/_mixins/links.pug
  3. 3 3
      services/web/app/views/admin/index.pug
  4. 1 1
      services/web/app/views/general/500.pug
  5. 1 1
      services/web/app/views/general/closed.pug
  6. 1 1
      services/web/app/views/layout/footer.pug
  7. 2 2
      services/web/app/views/layout/navbar.pug
  8. 2 1
      services/web/app/views/project/editor/history/previewPanelV2.pug
  9. 2 2
      services/web/app/views/project/invite/show.pug
  10. 1 1
      services/web/app/views/project/list.pug
  11. 4 1
      services/web/app/views/project/list/side-bar.pug
  12. 9 9
      services/web/app/views/project/v2-import.pug
  13. 1 1
      services/web/app/views/restore.pug
  14. 1 1
      services/web/app/views/scribtex-modal.pug
  15. 4 4
      services/web/app/views/subscriptions/_plans_page_tables.pug
  16. 2 2
      services/web/app/views/subscriptions/dashboard.pug
  17. 1 1
      services/web/app/views/subscriptions/dashboard/_change_plans_mixins.pug
  18. 1 1
      services/web/app/views/subscriptions/dashboard/_group_memberships.pug
  19. 1 1
      services/web/app/views/subscriptions/dashboard/_institution_memberships.pug
  20. 1 1
      services/web/app/views/subscriptions/dashboard/_personal_subscription_recurly.pug
  21. 1 1
      services/web/app/views/subscriptions/new.pug
  22. 1 1
      services/web/app/views/subscriptions/plans.pug
  23. 2 2
      services/web/app/views/subscriptions/successful_subscription.pug
  24. 2 2
      services/web/app/views/university/case_study.pug
  25. 2 2
      services/web/app/views/user/register.pug
  26. 12 3
      services/web/app/views/user/settings.pug
  27. 1 1
      services/web/app/views/user_membership/index.pug
  28. 5 2
      services/web/app/views/user_membership/new.pug
  29. 32 65
      services/web/public/src/directives/mathjax.js

+ 1 - 1
services/web/app/views/_mixins/faq_search.pug

@@ -1,7 +1,7 @@
 mixin faq_search(headerText, headerClass)
 	- if(typeof(settings.algolia) != "undefined" && typeof(settings.algolia.indexes) != "undefined" && typeof(settings.algolia.indexes.wiki) != "undefined")
 		if headerText
-			div(class=headerClass) #{headerText}
+			div(class=headerClass, ng-non-bindable) #{headerText}
 		.wiki(ng-controller="SearchWikiController")
 			form.project-search.form-horizontal(role="search")
 				.form-group.has-feedback.has-feedback-left

+ 13 - 13
services/web/app/views/_mixins/links.pug

@@ -15,32 +15,32 @@ mixin linkAdvisors(linkText, linkClass, track)
 		event-tracking-mb=mb
 		event-segmentation=mbSegmentation
 	)
-		| #{linkText ? linkText : 'advisor programme'}
+		span(ng-non-bindable) #{linkText ? linkText : 'advisor programme'}
 
 mixin linkBenefits(linkText, linkClass)
-	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/authors" class=linkClass ? linkClass : '')
+	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/authors" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'benefits'}
 		
 mixin linkBlog(linkText, linkClass, slug)
 	if slug
-		a(href=(settings.siteUrl ? settings.siteUrl : '') + "/blog/" + slug class=linkClass ? linkClass : '')
+		a(href=(settings.siteUrl ? settings.siteUrl : '') + "/blog/" + slug class=linkClass ? linkClass : '', ng-non-bindable)
 			| #{linkText ? linkText : 'blog'}
 
 mixin linkContact(linkText, linkClass)
-	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/contact" class=linkClass ? linkClass : '')
+	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/contact" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'contact'}
 
 mixin linkDash(linkText, linkClass)
-	a(href="/project" class=linkClass ? linkClass : '')
+	a(href="/project" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'project dashboard'}
 
 mixin linkEducation(linkText, linkClass)
-	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/edu" class=linkClass ? linkClass : '')
+	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/edu" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'teaching toolkit'}
 
 mixin linkEmail(linkText, linkClass, email)
 	- var emailAddress = email ? email : 'contact'
-	a(href="mailto:" + emailAddress + "@overleaf.com" class=linkClass ? linkClass : '')
+	a(href="mailto:" + emailAddress + "@overleaf.com" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'email'}
 
 mixin linkInvite(linkText, linkClass, track)
@@ -60,10 +60,10 @@ mixin linkInvite(linkText, linkClass, track)
 		event-tracking-mb=mb
 		event-segmentation=mbSegmentation
 	)
-		| #{linkText ? linkText : 'invite your friends'}
+		span(ng-non-bindable) #{linkText ? linkText : 'invite your friends'}
 
 mixin linkPlansAndPricing(linkText, linkClass)
-	a(href="/user/subscription/plans" class=linkClass ? linkClass : '')
+	a(href="/user/subscription/plans" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'plans and pricing'}
 
 mixin linkPrintNewTab(linkText, linkClass, icon, track)
@@ -88,14 +88,14 @@ mixin linkPrintNewTab(linkText, linkClass, icon, track)
 		if icon
 			i(class="fa fa-print")
 			|  
-		| #{linkText ? linkText : 'print'}
+		span(ng-non-bindable) #{linkText ? linkText : 'print'}
 
 mixin linkSignIn(linkText, linkClass, redirect)
-	a(href=`/login${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '')
+	a(href=`/login${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'sign in'}
 
 mixin linkSignUp(linkText, linkClass, redirect)
-	a(href=`/register${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '')
+	a(href=`/register${redirect ? '?redir=' + redirect : ''}` class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'sign up'}
 
 mixin linkTweet(linkText, linkClass, tweetText, track)
@@ -119,5 +119,5 @@ mixin linkTweet(linkText, linkClass, tweetText, track)
 	) #{linkText ? linkText : 'tweet'}
 
 mixin linkUniversities(linkText, linkClass)
-	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/universities" class=linkClass ? linkClass : '')
+	a(href=(settings.siteUrl ? settings.siteUrl : '') + "/for/universities" class=linkClass ? linkClass : '', ng-non-bindable)
 		| #{linkText ? linkText : 'universities'}

+ 3 - 3
services/web/app/views/admin/index.pug

@@ -11,7 +11,7 @@ block content
 						tabset(ng-cloak)
 							tab(heading="System Messages")
 								each message in systemMessages
-									.alert.alert-info.row-spaced #{message.content}
+									.alert.alert-info.row-spaced(ng-non-bindable) #{message.content}
 								hr
 								form(method='post', action='/admin/messages')
 									input(name="_csrf", type="hidden", value=csrfToken)
@@ -29,10 +29,10 @@ block content
 								.row-spaced
 									ul
 										each agents, url in openSockets
-											li #{url} - total : #{agents.length}
+											li(ng-non-bindable) #{url} - total : #{agents.length}
 												ul
 													each agent in agents
-														li #{agent}
+														li(ng-non-bindable) #{agent}
 
 							tab(heading="Close Editor")
 								.row-spaced

+ 1 - 1
services/web/app/views/general/500.pug

@@ -17,5 +17,5 @@ html.full-height(itemscope, itemtype='http://schema.org/Product')
 						)
 					.error-details
 						p.error-status Something went wrong, sorry.
-						p.error-description Our staff are probably looking into this, but if it continues, please contact us at #{settings.adminEmail}
+						p.error-description(ng-non-bindable) Our staff are probably looking into this, but if it continues, please contact us at #{settings.adminEmail}
 						a.error-btn(href="/") Home

+ 1 - 1
services/web/app/views/general/closed.pug

@@ -7,7 +7,7 @@ block content
 				.col-md-8.col-md-offset-2.text-center
 					.page-header
 						h1 Maintenance
-					p 
+					p (ng-non-bindable)
 						| Sorry, #{settings.appName} is briefly down for maintenance.
 						| We should be back within minutes, but if not, or you have
 						| an urgent request, please contact us at

+ 1 - 1
services/web/app/views/layout/footer.pug

@@ -37,7 +37,7 @@ footer.site-footer
 			ul.col-md-3.text-right
 
 				each item in nav.right_footer
-					li
+					li(ng-non-bindable)
 						if item.url
 							a(href=item.url, class=item.class, aria-label=item.label) !{item.text}
 						else

+ 2 - 2
services/web/app/views/layout/navbar.pug

@@ -6,7 +6,7 @@ nav.navbar.navbar-default.navbar-main
 			if settings.nav.custom_logo
 				a(href='/', aria-label=settings.appName, style='background-image:url("'+settings.nav.custom_logo+'")').navbar-brand
 			else if (nav.title)
-				a(href='/', aria-label=settings.appName).navbar-title #{nav.title}
+				a(href='/', aria-label=settings.appName, ng-non-bindable).navbar-title #{nav.title}
 			else
 				a(href='/', aria-label=settings.appName).navbar-brand
 
@@ -82,7 +82,7 @@ nav.navbar.navbar-default.navbar-main
 							b.caret
 						ul.dropdown-menu
 							li
-								div.subdued #{getUserEmail()}
+								div.subdued(ng-non-bindable) #{getUserEmail()}
 							li.divider
 							li
 								a(href="/user/settings") #{translate('Account Settings')}

+ 2 - 1
services/web/app/views/project/editor/history/previewPanelV2.pug

@@ -50,7 +50,8 @@
 			p
 				| #{translate("generic_history_error")} 
 				a(
-					ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}"
+					ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}",
+					ng-non-bindable
 				) #{settings.adminEmail}
 			p.clearfix
 				a.alert-link-as-btn.pull-right(

+ 2 - 2
services/web/app/views/project/invite/show.pug

@@ -9,12 +9,12 @@ block content
 						.page-header.text-centered
 							h1  #{translate("user_wants_you_to_see_project", {username:owner.first_name, projectname:""})}
 								em
-									span.project-name #{project.name} 
+									span.project-name(ng-non-bindable) #{project.name} 
 						.row.text-center
 							.col-md-12
 								p
 									| #{translate("accepting_invite_as")} 
-									em #{user.email}
+									em(ng-non-bindable) #{user.email}
 						.row
 							.col-md-12
 								form.form(

+ 1 - 1
services/web/app/views/project/list.pug

@@ -94,7 +94,7 @@ block content
 										ng-click="toggle()"
 									)
 										i.fa.fa-fw(ng-class="{ 'fa-chevron-up': !visible, 'fa-close': visible }" aria-hidden="true")
-										span.sr-only Toggle welcome to #{settings.appName} message
+										span.sr-only(ng-non-bindable) Toggle welcome to #{settings.appName} message
 									| Welcome to Overleaf v2!
 								div(ng-show="visible") #[a(href="https://www.overleaf.com/help/342-overleaf-v2-faq") Find out more].
 								if userIsFromOLv1(user)

+ 4 - 1
services/web/app/views/project/list/side-bar.pug

@@ -33,7 +33,10 @@
 			li.dropdown-header #{translate("institution")} #{translate("templates")}
 			for portal in portalTemplates
 				li
-					a.menu-indent(href=portal.url + "#templates") #{portal.name}
+					a.menu-indent(
+						href=portal.url + "#templates",
+						ng-non-bindable
+					) #{portal.name}
 
 
 

+ 9 - 9
services/web/app/views/project/v2-import.pug

@@ -27,9 +27,9 @@ block content
 					else
 						if hasOwner
 							p.text-center.row-spaced-small
-								| #[strong #{name}] has not yet been moved into the new version of
-								| Overleaf. You will need to move it in order to continue working
-								| on it. It should only take a few seconds.
+								| #[strong(ng-non-bindable) #{name}] has not yet been moved into
+								| the new version of Overleaf. You will need to move it in order
+								| to continue working on it. It should only take a few seconds.
 
 							form(
 								async-form="v2Import"
@@ -50,12 +50,12 @@ block content
 								a(href="/overleaf/project/" + projectId + "/download/zip") Download project zip file
 						else
 							p.text-center.row-spaced.small
-								| #[strong #{name}] has not yet been moved into the new version of
-								| Overleaf. This project was created anonymously and therefore
-								| cannot be automatically imported. Please download a zip file of
-								| the project and upload that to continue editing it. If you
-								| would like to delete this project after you have made a copy,
-								| please contact support.
+								| #[strong(ng-non-bindable) #{name}] has not yet been moved into
+								| the new version of Overleaf. This project was created
+								| anonymously and therefore cannot be automatically imported.
+								| Please download a zip file of the project and upload that to
+								| continue editing it. If you would like to delete this project
+								| after you have made a copy, please contact support.
 
 							.row-spaced.text-center
 								a.btn.btn-primary(href="/overleaf/project/" + projectId + "/download/zip") Download project zip file

+ 1 - 1
services/web/app/views/restore.pug

@@ -22,7 +22,7 @@ block content
 							each project in projects
 								tr
 									- project_id = project._id.toString()
-									td(width="50%") #{project.name}
+									td(width="50%", ng-non-bindable) #{project.name}
 									td(width="25%")
 										a.btn(href="/project/"+project_id+"/zip") Download latest version as Zip
 

+ 1 - 1
services/web/app/views/scribtex-modal.pug

@@ -5,4 +5,4 @@ script(type='text/ng-template', id='scribtexModalTemplate')
 		p ScribTeX has moved to <strong>https://scribtex.sharelatex.com</strong>. Please update your bookmarks.
 		p(style="text-align: center") You can find the page you were looking for here:
 		p(style="text-align: center")
-			a(href="https://scribtex.sharelatex.com"+scribtexPath, style="font-size: 16px") https://scribtex.sharelatex.com#{scribtexPath}
+			a(href="https://scribtex.sharelatex.com"+scribtexPath, style="font-size: 16px", ng-non-bindable) https://scribtex.sharelatex.com#{scribtexPath}

+ 4 - 4
services/web/app/views/subscriptions/_plans_page_tables.pug

@@ -28,7 +28,7 @@ mixin table_premium
 					else
 						| #{translate(feature.feature)}
 				for plan in feature.plans
-					td
+					td(ng-non-bindable)
 						if feature.value == 'str'
 							| #{plan}
 						else if plan
@@ -86,7 +86,7 @@ mixin table_student
 						span(tooltip=translate(feature.info)) #{translate(feature.feature)}
 					else
 						| #{translate(feature.feature)}
-				td
+				td(ng-non-bindable)
 					if feature.value == 'str'
 						| #{feature.plans.free}
 					else if feature.plans.free
@@ -95,9 +95,9 @@ mixin table_student
 					else
 						i.fa.fa-times(aria-hidden="true")
 						span.sr-only Feature included
-				td
+				td(ng-non-bindable)
 					+table_cell_student(feature)
-				td
+				td(ng-non-bindable)
 					+table_cell_student(feature)
 
 		tr

+ 2 - 2
services/web/app/views/subscriptions/dashboard.pug

@@ -41,10 +41,10 @@ block content
 						-if (!hasDisplayedSubscription)
 							-if (hasSubscription)
 								-hasDisplayedSubscription = true
-								p You're on an #{settings.appName} Paid plan. Contact
+								p(ng-non-bindable) You're on an #{settings.appName} Paid plan. Contact
 									a(href="mailto:support@overleaf.com") support@overleaf.com
 									|  to find out more.
 							-else
-								p You're on the #{settings.appName} Free plan.
+								p(ng-non-bindable) You're on the #{settings.appName} Free plan.
 								|
 								a(href="/user/subscription/plans").btn.btn-primary Upgrade now

+ 1 - 1
services/web/app/views/subscriptions/dashboard/_change_plans_mixins.pug

@@ -2,7 +2,7 @@ mixin printPlan(plan)
 	-if (!plan.hideFromUsers)
 		tr(ng-controller="ChangePlanFormController", ng-init="plan="+JSON.stringify(plan))
 			td
-				strong #{plan.name}
+				strong(ng-non-bindable) #{plan.name}
 			td
 				-if (plan.annual)
 					| {{price}} / #{translate("year")}

+ 1 - 1
services/web/app/views/subscriptions/dashboard/_group_memberships.pug

@@ -9,7 +9,7 @@ div(ng-controller="GroupMembershipController")
 				- if (groupSubscription.teamNotice && groupSubscription.teamNotice != '')
 					p
 						//- Team notice is sanitized in SubscriptionViewModelBuilder
-						em !{groupSubscription.teamNotice}
+						em(ng-non-bindable) !{groupSubscription.teamNotice}
 				span 
 					button.btn.btn-danger.text-capitalise(ng-click="removeSelfFromGroup('"+groupSubscription.admin_id._id+"')") #{translate("leave_group")}
 			hr

+ 1 - 1
services/web/app/views/subscriptions/dashboard/_institution_memberships.pug

@@ -4,7 +4,7 @@ each institution in confirmedMemberInstitutions
 		p
 			| You have a
 			|
-			strong Professional
+			strong(ng-non-bindable) Professional
 			|
 			| #{settings.appName} account as a confirmed member of
 			|

+ 1 - 1
services/web/app/views/subscriptions/dashboard/_personal_subscription_recurly.pug

@@ -11,7 +11,7 @@ div(ng-controller="RecurlySubscriptionController")
 				p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})} 
 					a(href, ng-click="switchToChangePlanView()", ng-if="showChangePlanButton") !{translate("change_plan")}.
 				-if (personalSubscription.recurly.trialEndsAtFormatted && personalSubscription.recurly.trial_ends_at > Date.now())
-					p You're on a free trial which ends on <strong>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
+					p You're on a free trial which ends on <strong ng-non-bindable>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>
 				p !{translate("next_payment_of_x_collectected_on_y", {paymentAmmount:"<strong>" + personalSubscription.recurly.price + "</strong>", collectionDate:"<strong>" + personalSubscription.recurly.nextPaymentDueAt + "</strong>"})}
 				p.pull-right
 				p

+ 1 - 1
services/web/app/views/subscriptions/new.pug

@@ -244,7 +244,7 @@ block content
 								
 							hr
 								
-							p.small.text-center We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
+							p.small.text-center(ng-non-bindable) We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
 
 
 	script(type="text/javascript").

+ 1 - 1
services/web/app/views/subscriptions/plans.pug

@@ -19,7 +19,7 @@ block content
 				.row
 					.col-md-12
 						.page-header.centered.plans-header.text-centered
-							h1.text-capitalize #{translate('get_instant_access_to')} #{settings.appName}
+							h1.text-capitalize(ng-non-bindable) #{translate('get_instant_access_to')} #{settings.appName}
 				.row
 					.col-md-8.col-md-offset-2
 						p.text-centered #{translate("sl_benefits_plans")}

+ 2 - 2
services/web/app/views/subscriptions/successful_subscription.pug

@@ -18,10 +18,10 @@ block content
 						p.letter-from-founders
 							p #{translate("thanks_for_subscribing_you_help_sl", {planName:subscription.plan.name})}
 							p #{translate("need_anything_contact_us_at")} 
-								a(href=`mailto:${settings.adminEmail}`) #{settings.adminEmail}
+								a(href=`mailto:${settings.adminEmail}`, ng-non-bindable) #{settings.adminEmail}
 								| .
 							p #{translate("regards")},
-								br
+								br(ng-non-bindable)
 								| The #{settings.appName} Team
 						p
 							a.btn.btn-primary(href="/project") &lt; #{translate("back_to_your_projects")}

+ 2 - 2
services/web/app/views/university/case_study.pug

@@ -5,7 +5,7 @@ block content
 		.container
 			.row
 				.col-md-12
-					h1  !{viewData.title}
+					h1(ng-non-bindable)  !{viewData.title}
 			.row.row-spaced
 
 	.pattern-container
@@ -14,6 +14,6 @@ block content
 				.row
 					.col-md-10.col-md-offset-1
 						.card
-							.row
+							.row(ng-non-bindable)
 								| !{viewData.html}
 

+ 2 - 2
services/web/app/views/user/register.pug

@@ -7,7 +7,7 @@ block content
 				.registration_message
 					if sharedProjectData.user_first_name !== undefined
 						h1  #{translate("user_wants_you_to_see_project", {username:sharedProjectData.user_first_name, projectname:""})}
-							em #{sharedProjectData.project_name}
+							em(ng-non-bindable) #{sharedProjectData.project_name}
 						div
 							| #{translate("join_sl_to_view_project")}.
 						div
@@ -26,5 +26,5 @@ block content
 							h1 #{translate("register")}
 						p
 							| Please contact 
-							strong #{settings.adminEmail} 
+							strong(ng-non-bindable) #{settings.adminEmail} 
 							| to create an account.

+ 12 - 3
services/web/app/views/user/settings.pug

@@ -41,7 +41,10 @@ block content
 												// show the email, non-editable
 												.form-group
 													label.control-label #{translate("email")}
-													div.form-control(readonly="true") #{user.email}
+													div.form-control(
+														readonly="true",
+														ng-non-bindable
+													) #{user.email}
 
 										if shouldAllowEditingDetails
 											.form-group
@@ -68,10 +71,16 @@ block content
 										else
 											.form-group
 												label.control-label #{translate("first_name")}
-												div.form-control(readonly="true") #{user.first_name}
+												div.form-control(
+													readonly="true",
+													ng-non-bindable
+												) #{user.first_name}
 											.form-group
 												label.control-label #{translate("last_name")}
-												div.form-control(readonly="true") #{user.last_name}
+												div.form-control(
+													readonly="true",
+													ng-non-bindable
+												) #{user.last_name}
 
 								.col-md-5.col-md-offset-1
 									h3 #{translate("change_password")}

+ 1 - 1
services/web/app/views/user_membership/index.pug

@@ -5,7 +5,7 @@ block content
 		.container
 			.row
 				.col-md-10.col-md-offset-1
-					h1 #{name || translate(translations.title)}
+					h1(ng-non-bindable) #{name || translate(translations.title)}
 					.card(ng-controller="UserMembershipController")
 						.page-header
 							.pull-right(ng-cloak)

+ 5 - 2
services/web/app/views/user_membership/new.pug

@@ -5,11 +5,14 @@ block content
 		.container
 			.row
 				.col-md-10.col-md-offset-1
-					h3 #{entityName} "#{entityId}" does not exists in v2
+					h3(ng-non-bindable) #{entityName} "#{entityId}" does not exists in v2
 					form(
 						enctype='application/json',
 						method='post',
 						action=''
 					)
 						input(name="_csrf", type="hidden", value=csrfToken)
-						button.btn.btn-primary.text-capitalize(type="submit") Create #{entityName} in v2
+						button.btn.btn-primary.text-capitalize(
+							type="submit",
+							ng-non-bindable
+						) Create #{entityName} in v2

+ 32 - 65
services/web/public/src/directives/mathjax.js

@@ -1,70 +1,37 @@
-/* eslint-disable
-    max-len,
-    no-undef,
-*/
-// TODO: This file was created by bulk-decaffeinate.
-// Fix any style issues and re-enable lint.
-/*
- * decaffeinate suggestions:
- * DS102: Remove unnecessary code created because of implicit returns
- * DS103: Rewrite code to no longer use __guard__
- * DS207: Consider shorter variations of null checks
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
-define(['base'], App =>
-  App.directive('mathjax', () => ({
-    link(scope, element, attrs) {
-      if (attrs.delimiter !== 'no-single-dollar') {
-        const inlineMathConfig = __guard__(
-          __guard__(
-            typeof MathJax !== 'undefined' && MathJax !== null
-              ? MathJax.Hub
-              : undefined,
-            x1 => x1.config
-          ),
-          x => x.tex2jax.inlineMath
-        )
-        const alreadyConfigured = _.find(
-          inlineMathConfig,
-          c => c[0] === '$' && c[1] === '$'
-        )
+/* global MathJax, _ */
 
-        if (alreadyConfigured == null) {
-          __guard__(
-            typeof MathJax !== 'undefined' && MathJax !== null
-              ? MathJax.Hub
-              : undefined,
-            x2 =>
-              x2.Config({
-                tex2jax: {
-                  inlineMath: inlineMathConfig.concat([['$', '$']])
-                }
-              })
+define(['base'], function(App) {
+  return App.directive('mathjax', function($compile) {
+    return {
+      link(scope, element, attrs) {
+        if (!(MathJax && MathJax.Hub)) return
+
+        const mathJaxContents = element.html()
+        const nonBindableEl = $compile('<span ng-non-bindable></span>')({})
+        element.html('').append(nonBindableEl)
+        nonBindableEl.html(mathJaxContents)
+
+        if (attrs.delimiter !== 'no-single-dollar') {
+          const inlineMathConfig =
+            MathJax.Hub.config && MathJax.Hub.config.tex2jax.inlineMath
+          const alreadyConfigured = _.find(
+            inlineMathConfig,
+            c => c[0] === '$' && c[1] === '$'
           )
+
+          if (!alreadyConfigured) {
+            MathJax.Hub.Config({
+              tex2jax: {
+                inlineMath: inlineMathConfig.concat([['$', '$']])
+              }
+            })
+          }
         }
-      }
 
-      return setTimeout(
-        () =>
-          __guard__(
-            typeof MathJax !== 'undefined' && MathJax !== null
-              ? MathJax.Hub
-              : undefined,
-            x3 =>
-              x3.Queue([
-                'Typeset',
-                typeof MathJax !== 'undefined' && MathJax !== null
-                  ? MathJax.Hub
-                  : undefined,
-                element.get(0)
-              ])
-          ),
-        0
-      )
+        setTimeout(() => {
+          MathJax.Hub.Queue(['Typeset', MathJax.Hub, element.get(0)])
+        }, 0)
+      }
     }
-  })))
-function __guard__(value, transform) {
-  return typeof value !== 'undefined' && value !== null
-    ? transform(value)
-    : undefined
-}
+  })
+})