{
{username && (
-
{t('buttons.sign-out')}
-
+
)}
diff --git a/client/src/components/Header/components/universal-nav.css b/client/src/components/Header/components/universal-nav.css
index b7c1aa46d34adf..c8bed3e19d6eaf 100644
--- a/client/src/components/Header/components/universal-nav.css
+++ b/client/src/components/Header/components/universal-nav.css
@@ -132,7 +132,7 @@
outline: none !important;
}
-a.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) {
+li > button.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) {
background-color: var(--danger-background);
color: var(--danger-color);
}
@@ -231,7 +231,7 @@ button.nav-link[aria-disabled='true'] {
}
}
-/* main menu must be at least as tall as lang menu (when displayed)
+/* main menu must be at least as tall as lang menu (when displayed)
unless there isn't enough view port height */
.nav-list.display-lang-menu {
min-height: min(var(--lang-menu-height), calc(100vh - var(--header-height)));
@@ -457,7 +457,7 @@ button.nav-link[aria-disabled='true'] {
left: 0;
}
-/* In mobile layout, prevent search input from hanging around if the
+/* In mobile layout, prevent search input from hanging around if the
menu is collapsed. */
.universal-nav-right
#toggle-button-nav[aria-expanded='false']
@@ -466,7 +466,7 @@ button.nav-link[aria-disabled='true'] {
display: none;
}
-/* In mobile layout, prevent search results from hanging around if the
+/* In mobile layout, prevent search results from hanging around if the
menu is collapsed. */
.universal-nav-right
#toggle-button-nav[aria-expanded='false']
diff --git a/client/src/components/Intro/index.tsx b/client/src/components/Intro/index.tsx
index 22e7bad8425383..5d33fee2f27133 100644
--- a/client/src/components/Intro/index.tsx
+++ b/client/src/components/Intro/index.tsx
@@ -6,7 +6,7 @@ import { Link, Spacer, Loader } from '../helpers';
import IntroDescription from './components/IntroDescription';
import './intro.css';
-import ResearchBannerx from './research-banner';
+import LearnAlert from './learn-alert';
interface IntroProps {
complete?: boolean;
@@ -16,6 +16,8 @@ interface IntroProps {
pending?: boolean;
slug?: string;
username?: string;
+ onDonationAlertClick: () => void;
+ isDonating: boolean;
}
const Intro = ({
@@ -24,7 +26,9 @@ const Intro = ({
pending,
complete,
completedChallengeCount,
- slug
+ slug,
+ onDonationAlertClick,
+ isDonating
}: IntroProps): JSX.Element => {
const { t } = useTranslation();
if (pending && !complete) {
@@ -56,7 +60,10 @@ const Intro = ({
-
+
{completedChallengeCount && slug && completedChallengeCount < 15 ? (
diff --git a/client/src/components/Intro/intro.test.tsx b/client/src/components/Intro/intro.test.tsx
index dd9dbc8a967377..d1000de9fa0364 100644
--- a/client/src/components/Intro/intro.test.tsx
+++ b/client/src/components/Intro/intro.test.tsx
@@ -60,7 +60,9 @@ const loggedInProps = {
navigate: () => jest.fn(),
pending: false,
slug: '/',
- username: 'DevelopmentUser'
+ username: 'DevelopmentUser',
+ isDonating: false,
+ onDonationAlertClick: () => jest.fn()
};
const loggedOutProps = {
@@ -70,5 +72,7 @@ const loggedOutProps = {
navigate: () => jest.fn(),
pending: false,
slug: '/',
- username: ''
+ username: '',
+ isDonating: false,
+ onDonationAlertClick: () => jest.fn()
};
diff --git a/client/src/components/Intro/learn-alert.tsx b/client/src/components/Intro/learn-alert.tsx
new file mode 100644
index 00000000000000..30b769929bd409
--- /dev/null
+++ b/client/src/components/Intro/learn-alert.tsx
@@ -0,0 +1,95 @@
+import React from 'react';
+import { Alert } from '@freecodecamp/react-bootstrap';
+import { useFeature } from '@growthbook/growthbook-react';
+import { useTranslation } from 'react-i18next';
+import { Link } from '../helpers';
+
+interface LearnAlertProps {
+ onDonationAlertClick: () => void;
+ isDonating: boolean;
+}
+
+const LearnAlert = ({
+ onDonationAlertClick,
+ isDonating
+}: LearnAlertProps): JSX.Element | null => {
+ const { t } = useTranslation();
+ const researchRecruitment = useFeature('show-research-recruitment-alert');
+ const universityCreation = useFeature('university-creation-alert');
+ const seasonalMessage = useFeature('seasonal-alert');
+
+ const researchRecruitmentAlert = (
+
+
+ Launching Oct 19: freeCodeCamp is teaming up with researchers
+ from Stanford and UPenn to study how to help people build strong coding
+ habits.
+
+
+ Would you like to get involved? You’ll get free coaching from our
+ scientists.
+
+
+
+ Learn about HabitLab
+
+
+
+ );
+
+ const seasonalMessageAlert = (
+
+
+ {t('learn.season-greetings-fcc')}
+
+ {t('learn.if-getting-value')}
+
+
+
+ {t('buttons.donate')}
+
+
+
+ );
+
+ const universityCreationAlert = (
+
+
+ {t('learn.building-a-university')}
+
+ {t('learn.if-help-university')}
+
+
+
+ {t('donate.become-supporter')}
+
+
+
+ );
+
+ if (researchRecruitment.on) return researchRecruitmentAlert;
+ if (universityCreation.on && !isDonating) return universityCreationAlert;
+ if (seasonalMessage.on) return seasonalMessageAlert;
+ return null;
+};
+
+LearnAlert.displayName = 'LearnAlert';
+
+export default LearnAlert;
diff --git a/client/src/components/Intro/research-banner.tsx b/client/src/components/Intro/research-banner.tsx
deleted file mode 100644
index 324b146bb4bf3b..00000000000000
--- a/client/src/components/Intro/research-banner.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { Alert, Button } from '@freecodecamp/react-bootstrap';
-import { useFeature } from '@growthbook/growthbook-react';
-
-const ResearchBannerx = (): JSX.Element | null => {
- const feature = useFeature('show-research-recruitment-alert');
- return feature.on ? (
-
-
- Launching Oct 19: freeCodeCamp is teaming up with researchers
- from Stanford and UPenn to study how to help people build strong coding
- habits.
-
-
- Would you like to get involved? You’ll get free coaching from our
- scientists.
-
-
-
-
-
- ) : null;
-};
-
-ResearchBannerx.displayName = 'ResearchBannerx';
-
-export default ResearchBannerx;
diff --git a/client/src/components/Map/__snapshots__/map.test.tsx.snap b/client/src/components/Map/__snapshots__/map.test.tsx.snap
deleted file mode 100644
index 078190f95fa774..00000000000000
--- a/client/src/components/Map/__snapshots__/map.test.tsx.snap
+++ /dev/null
@@ -1,535 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`
snapshot: Map 1`] = `
-
-`;
diff --git a/client/src/components/Map/index.tsx b/client/src/components/Map/index.tsx
index 01ea334f727106..a3e0fb8795ae47 100644
--- a/client/src/components/Map/index.tsx
+++ b/client/src/components/Map/index.tsx
@@ -1,141 +1,121 @@
-import { graphql, useStaticQuery } from 'gatsby';
import i18next from 'i18next';
import React from 'react';
import { SuperBlocks } from '../../../../config/certification-settings';
+import {
+ CurriculumMaps,
+ getAuditedSuperBlocks,
+ getNotAuditedSuperBlocks,
+ superBlockOrder
+} from '../../../../config/superblock-order';
+import { Languages } from '../../../../config/i18n';
import envData from '../../../../config/env.json';
-import { isAuditedCert } from '../../../../utils/is-audited';
import { generateIconComponent } from '../../assets/icons';
import LinkButton from '../../assets/icons/link-button';
-import { ChallengeNode } from '../../redux/prop-types';
import { Link, Spacer } from '../helpers';
+import { getSuperBlockTitleForMap } from '../../utils/superblock-map-titles';
import './map.css';
-const { curriculumLocale } = envData;
+const { curriculumLocale, showNewCurriculum, showUpcomingChanges } = envData;
interface MapProps {
currentSuperBlock?: SuperBlocks | null;
forLanding?: boolean;
}
-interface MapData {
- allChallengeNode: {
- nodes: ChallengeNode[];
- };
-}
-
-function createSuperBlockTitle(superBlock: SuperBlocks) {
- const superBlockTitle = i18next.t(`intro:${superBlock}.title`);
- return superBlock === 'coding-interview-prep'
- ? superBlockTitle
- : i18next.t('learn.cert-map-estimates.certs', {
- title: superBlockTitle
- });
-}
-
const linkSpacingStyle = {
display: 'flex',
justifyContent: 'space-between',
- alignItems: 'center'
+ alignItems: 'center',
+ gap: '15px'
};
-function renderLandingMap(nodes: ChallengeNode[]) {
- nodes = nodes.filter(
- ({ challenge }) => challenge.superBlock !== SuperBlocks.CodingInterviewPrep
+function MapLi({
+ superBlock,
+ landing = false
+}: {
+ superBlock: SuperBlocks;
+ landing: boolean;
+}) {
+ return (
+
+
+
+ {generateIconComponent(superBlock, 'map-icon')}
+ {getSuperBlockTitleForMap(superBlock)}
+
+ {landing && }
+
+
);
+}
+
+function renderLandingMap() {
+ const landingSuperOrder =
+ superBlockOrder[curriculumLocale as Languages][CurriculumMaps.Landing];
+
return (
);
}
-function renderLearnMap(
- nodes: ChallengeNode[],
- currentSuperBlock: MapProps['currentSuperBlock']
-) {
- nodes = nodes.filter(
- ({ challenge }) => challenge.superBlock !== currentSuperBlock
+function renderLearnMap(currentSuperBlock: MapProps['currentSuperBlock']) {
+ const tempAuditedSuperBlocks = getAuditedSuperBlocks({
+ language: curriculumLocale,
+ showNewCurriculum: showNewCurriculum.toString(),
+ showUpcomingChanges: showUpcomingChanges.toString()
+ });
+ const tempNotAuditedSuperBlocks = getNotAuditedSuperBlocks({
+ language: curriculumLocale,
+ showNewCurriculum: showNewCurriculum.toString(),
+ showUpcomingChanges: showUpcomingChanges.toString()
+ });
+
+ const auditedSuperBlocks = tempAuditedSuperBlocks.filter(
+ superBlock => superBlock !== currentSuperBlock
+ );
+
+ const notAuditedSuperBlocks = tempNotAuditedSuperBlocks.filter(
+ superBlock => superBlock !== currentSuperBlock
);
- return curriculumLocale === 'english' ? (
+
+ return (
- ) : (
-
- {nodes
- .filter(({ challenge }) =>
- isAuditedCert(curriculumLocale, challenge.superBlock)
- )
- .map(({ challenge }, i) => (
- -
-
-
- {generateIconComponent(challenge.superBlock, 'map-icon')}
- {createSuperBlockTitle(challenge.superBlock)}
-
-
-
- ))}
-
-
-
{i18next.t('learn.help-translate')}
-
- {i18next.t('learn.help-translate-link')}
-
-
-
- {nodes
- .filter(
- ({ challenge }) =>
- !isAuditedCert(curriculumLocale, challenge.superBlock)
- )
- .map(({ challenge }, i) => (
- -
+
+ {/* has not audited superblocks */}
+ {notAuditedSuperBlocks.length > 0 && (
+ <>
+ {' '}
+
+
+
+ {i18next.t('learn.help-translate')}{' '}
+
-
- {generateIconComponent(challenge.superBlock, 'map-icon')}
- {createSuperBlockTitle(challenge.superBlock)}
-
+ {i18next.t('learn.help-translate-link')}
-
- ))}
+
+
+ >
+ )}
+
+ {/* not audited superblocks */}
+ {notAuditedSuperBlocks.map((superBlock, i) => (
+
+ ))}
);
}
@@ -144,39 +124,9 @@ export function Map({
forLanding = false,
currentSuperBlock = null
}: MapProps): React.ReactElement {
- /*
- * this query gets the first challenge from each block and the first block
- * from each superblock, leaving you with one challenge from each
- * superblock
- */
- const data: MapData = useStaticQuery(graphql`
- query SuperBlockNodes {
- allChallengeNode(
- sort: { fields: [challenge___superOrder] }
- filter: { challenge: { order: { eq: 0 }, challengeOrder: { eq: 0 } } }
- ) {
- nodes {
- challenge {
- superBlock
- dashedName
- }
- }
- }
- }
- `);
-
- const nodes = data.allChallengeNode.nodes;
- const temp = [
- nodes[0],
- nodes[12],
- ...nodes.filter((_, i) => i !== 0 && i !== 12)
- ];
-
return (
- {forLanding
- ? renderLandingMap(temp)
- : renderLearnMap(temp, currentSuperBlock)}
+ {forLanding ? renderLandingMap() : renderLearnMap(currentSuperBlock)}
);
}
diff --git a/client/src/components/Map/map.test.tsx b/client/src/components/Map/map.test.tsx
deleted file mode 100644
index 336608bdf073d2..00000000000000
--- a/client/src/components/Map/map.test.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { render } from '@testing-library/react';
-import { useStaticQuery } from 'gatsby';
-import React from 'react';
-
-import mockChallengeNodes from '../../__mocks__/challenge-nodes';
-import { Map } from '.';
-
-beforeEach(() => {
- (useStaticQuery as jest.Mock).mockImplementationOnce(() => ({
- allChallengeNode: {
- nodes: mockChallengeNodes
- }
- }));
-});
-
-// set .scrollTo to avoid errors in default test environment
-window.scrollTo = jest.fn();
-
-test('
snapshot', () => {
- const { container } = render(
);
-
- expect(container).toMatchSnapshot('Map');
-});
-
-const props = {
- forLanding: true
-};
diff --git a/client/src/components/create-language-redirect.test.ts b/client/src/components/create-language-redirect.test.ts
index ac4ca35c2ab66f..48c2a7c899b81a 100644
--- a/client/src/components/create-language-redirect.test.ts
+++ b/client/src/components/create-language-redirect.test.ts
@@ -9,7 +9,7 @@ describe('createLanguageRedirect for clientLocale === english', () => {
const currentPageURL =
'https://www.freecodecamp.org/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
const chinesePageURL =
- 'https://chinese.freecodecamp.org/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
+ 'https://www.freecodecamp.org/chinese/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
const espanolPageURL =
'https://www.freecodecamp.org/espanol/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
const chineseTraditionalPageURL =
@@ -54,7 +54,7 @@ describe('createLanguageRedirect for clientLocale === english', () => {
describe('settings page', () => {
const currentPageURL = 'https://www.freecodecamp.org/settings';
- const chinesePageURL = 'https://chinese.freecodecamp.org/settings';
+ const chinesePageURL = 'https://www.freecodecamp.org/chinese/settings';
const espanolPageURL = 'https://www.freecodecamp.org/espanol/settings';
const chineseTraditionalPageURL =
'https://www.freecodecamp.org/chinese-traditional/settings';
@@ -103,7 +103,7 @@ describe('createLanguageRedirect for clientLocale === chinese', () => {
describe('challenge page', () => {
const currentPageURL =
- 'https://chinese.freecodecamp.org/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
+ 'https://www.freecodecamp.org/chinese/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
const englishPageURL =
'https://www.freecodecamp.org/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element';
const espanolPageURL =
@@ -149,7 +149,7 @@ describe('createLanguageRedirect for clientLocale === chinese', () => {
});
describe('settings page', () => {
- const currentPageURL = 'https://chinese.freecodecamp.org/settings';
+ const currentPageURL = 'https://www.freecodecamp.org/chinese/settings';
const englishPageURL = 'https://www.freecodecamp.org/settings';
const espanolPageURL = 'https://www.freecodecamp.org/espanol/settings';
const chineseTraditionalPageURL =
diff --git a/client/src/components/create-language-redirect.ts b/client/src/components/create-language-redirect.ts
index b7a529d03b98e8..b626c9e1c6fa97 100644
--- a/client/src/components/create-language-redirect.ts
+++ b/client/src/components/create-language-redirect.ts
@@ -13,12 +13,10 @@ const createLanguageRedirect = ({
.filter(item => (item !== clientLocale && item !== lang ? item : ''))
.join('/');
- const hostTail = window?.location?.host.split('.').slice(1).join('.');
- const nextClient = lang !== 'chinese' ? 'www' : 'chinese';
- const nextLocation = `${window?.location?.protocol}//${nextClient}.${hostTail}`;
+ const hostTail = window?.location?.host;
+ const nextLocation = `${window?.location?.protocol}//${hostTail}`;
- if (lang === 'english' || lang === 'chinese')
- return `${nextLocation}/${path}`;
+ if (lang === 'english') return `${nextLocation}/${path}`;
return `${nextLocation}/${lang}/${path}`;
};
diff --git a/client/src/components/layouts/default.tsx b/client/src/components/layouts/default.tsx
index 34d92382647936..f0e7b4ec673861 100644
--- a/client/src/components/layouts/default.tsx
+++ b/client/src/components/layouts/default.tsx
@@ -30,7 +30,7 @@ import { UserFetchState, User } from '../../redux/prop-types';
import BreadCrumb from '../../templates/Challenges/components/bread-crumb';
import Flash from '../Flash';
import { flashMessageSelector, removeFlashMessage } from '../Flash/redux';
-
+import SignoutModal from '../signout-modal';
import Footer from '../Footer';
import Header from '../Header';
import OfflineWarning from '../OfflineWarning';
@@ -219,6 +219,7 @@ class DefaultLayout extends Component
{
removeFlashMessage={removeFlashMessage}
/>
) : null}
+
{isChallenge && (
div:only-child {
+ height: 100%;
+ overflow: auto;
+}
+
+#content-start {
+ min-height: 0;
+ height: 100%;
+}
+
+#content-start > div {
+ height: 100%;
}
h1 {
@@ -460,7 +477,7 @@ fieldset[disabled] .btn-primary.focus {
.map-icon {
width: 35px;
max-height: 45px;
- margin-right: 20px;
+ margin-inline: 5px;
}
.cert-header-icon {
@@ -775,6 +792,20 @@ blockquote .small {
border-color: #31708f;
}
+.annual-donation-alert {
+ background: linear-gradient(
+ -10deg,
+ rgba(217, 237, 247, 1) 35%,
+ rgba(237, 202, 216, 0) 75%,
+ rgb(255 215 224) 100%
+ ),
+ radial-gradient(
+ circle,
+ rgba(255, 202, 225, 1) 0%,
+ rgba(218, 234, 252, 1) 100%
+ );
+}
+
/* gatsby 404 */
#search {
background-color: var(--quaternary-background);
diff --git a/client/src/components/layouts/index.ts b/client/src/components/layouts/index.ts
deleted file mode 100644
index c97db04f81187a..00000000000000
--- a/client/src/components/layouts/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export { default as CertificationLayout } from './certification';
-export { default as DefaultLayout } from './default';
-export { default as TcIntegrationLayout } from './tc-integration';
-export { default as LearnLayout } from './learn';
diff --git a/client/src/components/layouts/learn.css b/client/src/components/layouts/learn.css
index 292b987c9c36fa..0f0a1089c6ae85 100644
--- a/client/src/components/layouts/learn.css
+++ b/client/src/components/layouts/learn.css
@@ -1,9 +1,17 @@
+#learn-app-wrapper,
+#learn-app-wrapper .desktop-layout,
+#learn-app-wrapper .reflex-container.vertical {
+ height: 100%;
+}
+
#learn-app-wrapper .desktop-layout {
display: flex;
flex-direction: column;
- height: calc(
- 100vh - var(--header-height, 0px) - var(--flash-message-height, 0px)
- );
+}
+
+#learn-app-wrapper .reflex-container.vertical {
+ min-height: 0;
+ flex-grow: 1;
}
#learn-app-wrapper .reflex-container.vertical > .reflex-splitter,
diff --git a/client/src/components/signout-modal/index.tsx b/client/src/components/signout-modal/index.tsx
new file mode 100644
index 00000000000000..ec07cf3be54cd1
--- /dev/null
+++ b/client/src/components/signout-modal/index.tsx
@@ -0,0 +1,100 @@
+import React from 'react';
+import { Button, Modal } from '@freecodecamp/react-bootstrap';
+import { bindActionCreators, Dispatch, AnyAction } from 'redux';
+import { createSelector } from 'reselect';
+import { connect } from 'react-redux';
+import { useTranslation } from 'react-i18next';
+
+import { ButtonSpacer } from '../helpers';
+import { hardGoTo as navigate, closeSignoutModal } from '../../redux/actions';
+import { isSignoutModalOpenSelector } from '../../redux/selectors';
+import { apiLocation } from '../../../../config/env.json';
+
+import './signout-modal.css';
+
+const mapStateToProps = createSelector(
+ isSignoutModalOpenSelector,
+ (show: boolean) => ({
+ show
+ })
+);
+
+const mapDispatchToProps = (dispatch: Dispatch) =>
+ bindActionCreators(
+ {
+ navigate,
+ closeSignoutModal
+ },
+ dispatch
+ );
+
+type SignoutModalProps = {
+ navigate: (path: string) => void;
+ closeSignoutModal: () => void;
+ show: boolean;
+};
+
+function SignoutModal(props: SignoutModalProps): JSX.Element {
+ const { show, closeSignoutModal, navigate } = props;
+ const { t } = useTranslation();
+
+ const handleModalHide = () => {
+ closeSignoutModal();
+ };
+
+ const handleSignout = () => {
+ closeSignoutModal();
+ navigate(`${apiLocation}/signout`);
+ };
+
+ return (
+
+
+
+ {t('signout.heading')}
+
+
+
+
+ {t('signout.p1')}
+
+ {t('signout.p2')}
+
+
+
+
+
+
+ );
+}
+
+SignoutModal.displayName = 'SignoutModal';
+
+export default connect(mapStateToProps, mapDispatchToProps)(SignoutModal);
diff --git a/client/src/components/signout-modal/signout-modal.css b/client/src/components/signout-modal/signout-modal.css
new file mode 100644
index 00000000000000..11c065b7c0b081
--- /dev/null
+++ b/client/src/components/signout-modal/signout-modal.css
@@ -0,0 +1,12 @@
+.btn-signout {
+ background-color: var(--danger-color);
+ color: var(--danger-background);
+ border-color: var(--danger-background);
+}
+
+.btn-signout:hover,
+.btn-signout:focus {
+ color: var(--danger-color);
+ background-color: var(--danger-background);
+ border-color: var(--danger-background);
+}
diff --git a/client/src/pages/learn.tsx b/client/src/pages/learn.tsx
index 96b1faa7fd8259..b534563989170f 100644
--- a/client/src/pages/learn.tsx
+++ b/client/src/pages/learn.tsx
@@ -5,6 +5,7 @@ import Helmet from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
+import { bindActionCreators, Dispatch } from 'redux';
import Intro from '../components/Intro';
import Map from '../components/Map';
@@ -16,6 +17,8 @@ import {
userFetchStateSelector
} from '../redux/selectors';
+import { executeGA } from '../redux/actions';
+
interface FetchState {
pending: boolean;
complete: boolean;
@@ -26,6 +29,7 @@ interface User {
name: string;
username: string;
completedChallengeCount: number;
+ isDonating: boolean;
}
const mapStateToProps = createSelector(
@@ -48,6 +52,7 @@ interface LearnPageProps {
fetchState: FetchState;
state: Record;
user: User;
+ executeGA: (payload: Record) => void;
data: {
challengeNode: {
challenge: {
@@ -57,10 +62,14 @@ interface LearnPageProps {
};
}
+const mapDispatchToProps = (dispatch: Dispatch) =>
+ bindActionCreators({ executeGA }, dispatch);
+
function LearnPage({
isSignedIn,
+ executeGA,
fetchState: { pending, complete },
- user: { name = '', completedChallengeCount = 0 },
+ user: { name = '', completedChallengeCount = 0, isDonating = false },
data: {
challengeNode: {
challenge: {
@@ -71,6 +80,15 @@ function LearnPage({
}: LearnPageProps) {
const { t } = useTranslation();
+ const onDonationAlertClick = () => {
+ executeGA({
+ type: 'event',
+ data: {
+ category: 'Donation Related',
+ action: `learn donation alert click`
+ }
+ });
+ };
return (
@@ -84,6 +102,8 @@ function LearnPage({
name={name}
pending={pending}
slug={slug}
+ onDonationAlertClick={onDonationAlertClick}
+ isDonating={isDonating}
/>
@@ -96,7 +116,7 @@ function LearnPage({
LearnPage.displayName = 'LearnPage';
-export default connect(mapStateToProps, null)(LearnPage);
+export default connect(mapStateToProps, mapDispatchToProps)(LearnPage);
export const query = graphql`
query FirstChallenge {
diff --git a/client/src/pages/learn/back-end-development-and-apis/basic-node-and-express/index.md b/client/src/pages/learn/back-end-development-and-apis/basic-node-and-express/index.md
index 292abe08289e05..31c46e3db7d9bb 100644
--- a/client/src/pages/learn/back-end-development-and-apis/basic-node-and-express/index.md
+++ b/client/src/pages/learn/back-end-development-and-apis/basic-node-and-express/index.md
@@ -15,6 +15,13 @@ Node.js is a JavaScript runtime that allows developers to write backend (server-
Express, while not included with Node.js, is another module often used with it. Express runs between the server created by Node.js and the frontend pages of a web application. Express also handles an application's routing. Routing directs users to the correct page based on their interaction with the application. While there are alternatives to using Express, its simplicity makes it a good place to begin when learning the interaction between a backend powered by Node.js and the frontend.
-Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using this link or clone this repository on GitHub! If you use Replit, remember to save the link to your project somewhere safe!
diff --git a/client/src/pages/learn/back-end-development-and-apis/managing-packages-with-npm/index.md b/client/src/pages/learn/back-end-development-and-apis/managing-packages-with-npm/index.md
index 38c28434e886a1..43ac12c693f35a 100644
--- a/client/src/pages/learn/back-end-development-and-apis/managing-packages-with-npm/index.md
+++ b/client/src/pages/learn/back-end-development-and-apis/managing-packages-with-npm/index.md
@@ -14,6 +14,14 @@ npm saves packages in a folder named node_modules
. These packages c
2. locally within a project's own node_modules
folder, accessible only to that project.
Most developers prefer to install packages local to each project to create a separation between the dependencies of different projects.
-Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
+
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using this link or clone this repository on GitHub! If you use Replit, remember to save the link to your project somewhere safe!
diff --git a/client/src/pages/learn/back-end-development-and-apis/mongodb-and-mongoose/index.md b/client/src/pages/learn/back-end-development-and-apis/mongodb-and-mongoose/index.md
index faae71b2f44683..c4f27f197ad7ee 100644
--- a/client/src/pages/learn/back-end-development-and-apis/mongodb-and-mongoose/index.md
+++ b/client/src/pages/learn/back-end-development-and-apis/mongodb-and-mongoose/index.md
@@ -16,7 +16,14 @@ While there are many non-relational databases, Mongo's use of JSON as its docume
Mongoose.js is an npm module for Node.js that allows you to write objects for Mongo as you would in JavaScript. This can make it easier to construct documents for storage in Mongo.
-Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using [this link](https://replit.com/github/freeCodeCamp/boilerplate-mongomongoose) or clone [this repository](https://github.com/freeCodeCamp/boilerplate-mongomongoose/) on GitHub! If you use Replit, remember to save the link to your project somewhere safe!
diff --git a/client/src/pages/learn/information-security/information-security-with-helmetjs/index.md b/client/src/pages/learn/information-security/information-security-with-helmetjs/index.md
index f1ff1f9963f598..43eebfa790e037 100644
--- a/client/src/pages/learn/information-security/information-security-with-helmetjs/index.md
+++ b/client/src/pages/learn/information-security/information-security-with-helmetjs/index.md
@@ -8,6 +8,13 @@ superBlock: Information Security
HelmetJS is a type of middleware for Express-based applications that automatically sets HTTP headers to prevent sensitive information from unintentionally being passed between the server and client. While HelmetJS does not account for all situations, it does include support for common ones like Content Security Policy, XSS Filtering, and HTTP Strict Transport Security, among others. HelmetJS can be installed on an Express project from npm, after which each layer of protection can be configured to best fit the project.
-Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge, you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally, you may choose to write your project on another platform, but it must be publicly visible for our testing.
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using this link or clone this repository on GitHub! If you use Replit, remember to save the link to your project somewhere safe!
diff --git a/client/src/pages/learn/quality-assurance/advanced-node-and-express/index.md b/client/src/pages/learn/quality-assurance/advanced-node-and-express/index.md
index 9c4688022fa5c6..eab946f481d79e 100644
--- a/client/src/pages/learn/quality-assurance/advanced-node-and-express/index.md
+++ b/client/src/pages/learn/quality-assurance/advanced-node-and-express/index.md
@@ -8,6 +8,15 @@ superBlock: Quality Assurance
_Authentication_ is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.
-The most common and easiest way to use authentication middleware for Node.js is [Passport](http://passportjs.org/). It is easy to learn, light-weight, and extremely flexible allowing for many _strategies_, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of _Pug_ and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
+The most common and easiest way to use authentication middleware for Node.js is [Passport](http://passportjs.org/). It is easy to learn, light-weight, and extremely flexible allowing for many _strategies_, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of _Pug_ and web sockets which allow for real time communication between all your clients and your server.
+
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using [this link](https://replit.com/github/freeCodeCamp/boilerplate-advancednode) or clone [this repository](https://github.com/freeCodeCamp/boilerplate-advancednode/) on GitHub! If you use Replit, remember to save the link to your project somewhere safe.
diff --git a/client/src/pages/learn/quality-assurance/quality-assurance-and-testing-with-chai/index.md b/client/src/pages/learn/quality-assurance/quality-assurance-and-testing-with-chai/index.md
index 40b3a81f110001..84aed80ba10471 100644
--- a/client/src/pages/learn/quality-assurance/quality-assurance-and-testing-with-chai/index.md
+++ b/client/src/pages/learn/quality-assurance/quality-assurance-and-testing-with-chai/index.md
@@ -8,6 +8,13 @@ superBlock: Quality Assurance
As your programs become more complex, you need to test them often to make sure any new code you add doesn't break the program's original functionality. Chai is a JavaScript testing library that helps you check that your program still behaves the way you expect it to after you make changes. Using Chai, you can write tests that describe your program's requirements and see if your program meets them.
-Working on these challenges will involve you writing your code on Replit on our starter project. After completing each challenge you can copy your public Replit URL (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
+Working on these challenges involves writing code on Replit in our starter project.
+
+- Start by importing the project on Replit.
+- Next, you will see a .replit
window.
+- Select Use run command
and click the Done
button.
+- Complete each challenge and copy the public Replit URL (to the homepage of your app) into the challenge screen to test it!
+
+Optionally, you may write your project on another platform, but it must be publicly visible for our testing.
Start this project on Replit using [this link](https://replit.com/github/freeCodeCamp/boilerplate-mochachai) or clone [this repository](https://github.com/freeCodeCamp/boilerplate-mochachai/) on GitHub! If you use Replit, remember to save the link to your project somewhere safe!
diff --git a/client/src/redux/action-types.js b/client/src/redux/action-types.js
index 9489f104bab0d8..22465beb90f397 100644
--- a/client/src/redux/action-types.js
+++ b/client/src/redux/action-types.js
@@ -7,12 +7,14 @@ export const actionTypes = createTypes(
'appMount',
'allowBlockDonationRequests',
'hardGoTo',
- 'closeDonationModal',
'hideCodeAlly',
'preventBlockDonationRequests',
'preventProgressDonationRequests',
'tryToShowDonationModal',
'openDonationModal',
+ 'closeDonationModal',
+ 'openSignoutModal',
+ 'closeSignoutModal',
'onlineStatusChange',
'serverStatusChange',
'resetUserData',
diff --git a/client/src/redux/actions.js b/client/src/redux/actions.js
index 86a4ee014b569f..a540a71d58cd76 100644
--- a/client/src/redux/actions.js
+++ b/client/src/redux/actions.js
@@ -109,3 +109,6 @@ export const tryToShowCodeAlly = createAction(actionTypes.tryToShowCodeAlly);
export const updateCurrentChallengeId = createAction(
actionTypes.updateCurrentChallengeId
);
+
+export const closeSignoutModal = createAction(actionTypes.closeSignoutModal);
+export const openSignoutModal = createAction(actionTypes.openSignoutModal);
diff --git a/client/src/redux/index.js b/client/src/redux/index.js
index 6bd494f2c08358..a87e06c2ce0180 100644
--- a/client/src/redux/index.js
+++ b/client/src/redux/index.js
@@ -60,6 +60,7 @@ export const initialState = {
},
sessionMeta: { activeDonations: 0 },
showDonationModal: false,
+ showSignoutModal: false,
isOnline: true,
isServerOnline: true,
donationFormState: {
@@ -286,6 +287,14 @@ export const reducer = handleActions(
appUsername: '',
user: {}
}),
+ [actionTypes.openSignoutModal]: state => ({
+ ...state,
+ showSignoutModal: true
+ }),
+ [actionTypes.closeSignoutModal]: state => ({
+ ...state,
+ showSignoutModal: false
+ }),
[actionTypes.showCert]: state => ({
...state,
showCert: {},
diff --git a/client/src/redux/selectors.js b/client/src/redux/selectors.js
index b751b3f0192166..e9a561d6067527 100644
--- a/client/src/redux/selectors.js
+++ b/client/src/redux/selectors.js
@@ -26,6 +26,8 @@ export const isServerOnlineSelector = state => state[MainApp].isServerOnline;
export const isSignedInSelector = state => !!state[MainApp].appUsername;
export const isDonationModalOpenSelector = state =>
state[MainApp].showDonationModal;
+export const isSignoutModalOpenSelector = state =>
+ state[MainApp].showSignoutModal;
export const recentlyClaimedBlockSelector = state =>
state[MainApp].recentlyClaimedBlock;
export const donationFormStateSelector = state =>
diff --git a/client/src/redux/types.ts b/client/src/redux/types.ts
index 2285777263c8c9..0c56a1c4bd0735 100644
--- a/client/src/redux/types.ts
+++ b/client/src/redux/types.ts
@@ -26,6 +26,7 @@ export interface State {
activeDonations: number;
};
showDonationModal: boolean;
+ showSignoutModal: boolean;
isOnline: boolean;
donationFormState: DefaultDonationFormState;
};
diff --git a/client/src/templates/Challenges/classic/classic.css b/client/src/templates/Challenges/classic/classic.css
index e405fa5baaa158..62a31f1bfb17d3 100644
--- a/client/src/templates/Challenges/classic/classic.css
+++ b/client/src/templates/Challenges/classic/classic.css
@@ -11,10 +11,6 @@
top: -999em;
}
-.monaco-editor .editor-widget {
- display: none !important;
-}
-
.monaco-menu .monaco-action-bar.vertical .action-item:nth-last-child(n + 5),
.monaco-menu .monaco-action-bar.vertical .action-item:last-child,
.monaco-menu .monaco-action-bar.vertical .action-label.separator {
@@ -64,6 +60,12 @@
margin: 0 auto;
}
+#mobile-layout {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
#mobile-layout .nav-tabs {
margin-left: 2px;
display: flex;
@@ -85,10 +87,16 @@
}
#mobile-layout .tab-content {
- height: calc(
- 100vh - var(--header-height, 0px) - var(--flash-message-height, 0px) - 69px
- );
- overflow-y: auto;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ overflow-y: hidden;
+}
+
+#mobile-layout-pane-editor {
+ display: flex;
+ flex-direction: column;
}
.action-row {
diff --git a/client/src/templates/Challenges/classic/editor.css b/client/src/templates/Challenges/classic/editor.css
index 72c1b05990c748..0288f12dbf2269 100644
--- a/client/src/templates/Challenges/classic/editor.css
+++ b/client/src/templates/Challenges/classic/editor.css
@@ -160,7 +160,8 @@ textarea.inputarea {
}
.test-feedback p {
- margin: 0;
+ margin: 0.45rem 0 0;
+ font-family: 'Lato', sans-serif;
}
.test-feedback h2 {
@@ -170,7 +171,7 @@ textarea.inputarea {
padding-right: 0.445rem;
/* using float instead of inline display so screen readers recognize h2 as a block element */
float: left;
- margin: 0;
+ margin: 0.5em 0 0;
}
.test-feedback h2:after {
@@ -180,16 +181,21 @@ textarea.inputarea {
.test-feedback svg {
height: 1.1rem;
width: auto;
- margin-right: 0.5rem;
+ margin-top: 0.5rem;
}
-.test-feedback > div {
+.test-feedback .test-status,
+.test-feedback .hint-status {
+ margin-top: 1rem;
display: flex;
+ gap: 0.5rem;
flex-direction: row;
}
.test-status-description,
.hint-description {
+ display: flex;
+ gap: 0.5rem;
width: 100%;
}
@@ -215,11 +221,11 @@ textarea.inputarea {
.lower-jaw-icon-bar {
overflow: hidden;
display: flex;
+ gap: 10px;
flex-direction: row;
}
.lower-jaw-icon-bar > button {
line-height: 0;
- margin-right: 10px;
}
.lower-jaw-icon-bar > button:focus {
diff --git a/client/src/templates/Challenges/classic/editor.tsx b/client/src/templates/Challenges/classic/editor.tsx
index 643c19064ebd46..49b49cf851de73 100644
--- a/client/src/templates/Challenges/classic/editor.tsx
+++ b/client/src/templates/Challenges/classic/editor.tsx
@@ -7,7 +7,7 @@ import type {
editor
// eslint-disable-next-line import/no-duplicates
} from 'monaco-editor/esm/vs/editor/editor.api';
-import { highlightAllUnder } from 'prismjs';
+import Prism from 'prismjs';
import React, {
useEffect,
Suspense,
@@ -69,6 +69,7 @@ import {
import GreenPass from '../../../assets/icons/green-pass';
import Code from '../../../assets/icons/code';
import ExternalLink from '../../../assets/icons/link-external';
+import { enhancePrismAccessibility } from '../utils/index';
import LowerJaw from './lower-jaw';
import './editor.css';
@@ -455,6 +456,12 @@ const Editor = (props: EditorProps): JSX.Element => {
newLine.run();
}
);
+ // @ts-ignore
+ editor._standaloneKeybindingService.addDynamicKeybinding(
+ '-actions.find',
+ null,
+ () => {}
+ );
/* eslint-enable */
editor.addAction({
id: 'execute-challenge',
@@ -735,7 +742,8 @@ const Editor = (props: EditorProps): JSX.Element => {
descContainer.appendChild(jawHeading);
descContainer.appendChild(desc);
desc.innerHTML = description;
- highlightAllUnder(desc);
+ Prism.hooks.add('complete', enhancePrismAccessibility);
+ Prism.highlightAllUnder(desc);
domNode.style.userSelect = 'text';
diff --git a/client/src/templates/Challenges/codeally/show.tsx b/client/src/templates/Challenges/codeally/show.tsx
index 873633c0f326ce..8b27e8cab2d1e4 100644
--- a/client/src/templates/Challenges/codeally/show.tsx
+++ b/client/src/templates/Challenges/codeally/show.tsx
@@ -279,32 +279,33 @@ class ShowCodeAlly extends Component {
- {isSignedIn && challengeType === challengeTypes.codeAllyCert && (
- <>
-
- {t('learn.complete-both-steps')}
-
-
-
- {t('learn.step-1')}
- {(isPartiallyCompleted || isCompleted) && (
-
- )}
-
-
- {t('learn.runs-in-vm')}
-
-
-
-
- >
- )}
+ {isSignedIn &&
+ challengeType === challengeTypes.codeAllyCert && (
+ <>
+
+ {t('learn.complete-both-steps')}
+
+
+
+ {t('learn.step-1')}
+ {(isPartiallyCompleted || isCompleted) && (
+
+ )}
+
+
+ {t('learn.runs-in-vm')}
+
+
+
+
+ >
+ )}
{
: t('buttons.click-start-course')}
- {isSignedIn && challengeType === challengeTypes.codeAllyCert && (
- <>
-
-
- {t('learn.step-2')}
- {isCompleted && (
-
+
+
+ {t('learn.step-2')}
+ {isCompleted && (
+
+ )}
+
+
+ {t('learn.submit-public-url')}
+
+
+
+
+
- )}
-
-
- {t('learn.submit-public-url')}
-
-
-
-
-
- >
- )}
+ >
+ )}
diff --git a/client/src/templates/Challenges/components/__snapshots__/challenge-title.test.tsx.snap b/client/src/templates/Challenges/components/__snapshots__/challenge-title.test.tsx.snap
index 2810649fe79a6e..49a09d687262d2 100644
--- a/client/src/templates/Challenges/components/__snapshots__/challenge-title.test.tsx.snap
+++ b/client/src/templates/Challenges/components/__snapshots__/challenge-title.test.tsx.snap
@@ -15,16 +15,9 @@ exports[` renders correctly 1`] = `
diff --git a/client/src/templates/Challenges/components/prism-formatted.tsx b/client/src/templates/Challenges/components/prism-formatted.tsx
index dfb54222afe8fb..298c1509ae8edb 100644
--- a/client/src/templates/Challenges/components/prism-formatted.tsx
+++ b/client/src/templates/Challenges/components/prism-formatted.tsx
@@ -1,56 +1,22 @@
import Prism from 'prismjs';
import React, { useRef, useEffect } from 'react';
+import { enhancePrismAccessibility } from '../utils';
interface PrismFormattedProps {
className?: string;
text: string;
- lineNumbers?: boolean;
- darkTheme?: boolean;
}
-/**
- * Add css formatting classes to the elements based on showLineNumbers and darkTheme params
- * @param container
- * @param showLineNumbers
- * @param darkTheme
- */
-const addFormattingClassesForPres = (
- container: HTMLElement,
- showLineNumbers = true,
- darkTheme = true
-) => {
- const codeBlocks: HTMLElement[] = [].slice.call(
- container.querySelectorAll('[class*="language-"]')
- );
- // we want to formatt the element, not the , get parent if current element is not PRE
- const preElements: HTMLPreElement[] = codeBlocks.map(
- c => (c.nodeName === 'PRE' ? c : c.parentElement) as HTMLPreElement
- );
-
- for (const pre of preElements) {
- pre.classList.toggle('line-numbers', showLineNumbers);
- pre.classList.toggle('dark-palette', darkTheme);
- }
-};
-
-function PrismFormatted({
- className,
- text,
- ...props
-}: PrismFormattedProps): JSX.Element {
+function PrismFormatted({ className, text }: PrismFormattedProps): JSX.Element {
const instructionsRef = useRef(null);
useEffect(() => {
// Just in case 'current' has not been created, though it should have been.
if (instructionsRef.current) {
- addFormattingClassesForPres(
- instructionsRef.current,
- props.lineNumbers,
- props.darkTheme
- );
+ Prism.hooks.add('complete', enhancePrismAccessibility);
Prism.highlightAllUnder(instructionsRef.current);
}
- }, [props.darkTheme, props.lineNumbers]);
+ }, []);
return (
-
Tests
+
+ {t('learn.editor-tabs.tests')}
+
{testSuiteTests.map(({ err, pass = false, text = '' }, index) => {
const isInitial = !pass && !err;
diff --git a/client/src/templates/Challenges/rechallenge/transformers.js b/client/src/templates/Challenges/rechallenge/transformers.js
index f04f0de5bfc37a..4abd8943a2eaaa 100644
--- a/client/src/templates/Challenges/rechallenge/transformers.js
+++ b/client/src/templates/Challenges/rechallenge/transformers.js
@@ -211,24 +211,16 @@ export const embedFilesInHtml = async function (challengeFiles) {
const style = contentDocument.createElement('style');
style.classList.add('fcc-injected-styles');
style.innerHTML = stylesCss?.contents;
- link.parentNode.replaceChild(style, link);
- } else if (stylesCss?.contents) {
- // automatic linking of style contents to html
- const style = contentDocument.createElement('style');
- style.classList.add('fcc-injected-styles');
- style.innerHTML = stylesCss?.contents;
- contentDocument.head.appendChild(style);
+
+ link.parentNode.appendChild(style);
+
+ link.removeAttribute('href');
+ link.dataset.href = 'styles.css';
}
if (script) {
- const newScript = contentDocument.createElement('script');
- newScript.innerHTML = scriptJs?.contents;
- script.parentNode.replaceChild(newScript, script);
- }
- if (indexJsx?.contents) {
- // automatic linking of jsx to html
- const newScript = contentDocument.createElement('script');
- newScript.innerHTML = indexJsx?.contents;
- contentDocument.head.appendChild(newScript);
+ script.innerHTML = scriptJs?.contents;
+ script.removeAttribute('src');
+ script.setAttribute('data-src', 'script.js');
}
return {
contents: documentElement.innerHTML
diff --git a/client/src/templates/Challenges/utils/index.ts b/client/src/templates/Challenges/utils/index.ts
index 2d6e96dee8be1a..81f0fb5146b829 100644
--- a/client/src/templates/Challenges/utils/index.ts
+++ b/client/src/templates/Challenges/utils/index.ts
@@ -1,3 +1,4 @@
+import i18next from 'i18next';
import envData from '../../../../../config/env.json';
const { forumLocation } = envData;
@@ -31,3 +32,37 @@ export function transformEditorLink(url: string): string {
'//glitch.com/edit/#!/$'
);
}
+
+export function enhancePrismAccessibility(
+ prismEnv: Prism.hooks.ElementHighlightedEnvironment
+) {
+ const langs: { [key: string]: string } = {
+ js: 'JavaScript',
+ javascript: 'JavaScript',
+ css: 'CSS',
+ html: 'HTML',
+ python: 'python',
+ py: 'python',
+ xml: 'XML',
+ jsx: 'JSX',
+ scss: 'SCSS',
+ sql: 'SQL',
+ http: 'HTTP',
+ json: 'JSON',
+ pug: 'pug'
+ };
+ const parent = prismEnv?.element?.parentElement;
+ if (parent && parent.nodeName === 'PRE' && parent.tabIndex === 0) {
+ parent.setAttribute('role', 'region');
+ const codeType = prismEnv.element?.className
+ .replace(/language-(.*)/, '$1')
+ .toLowerCase();
+ const codeName = langs[codeType] || '';
+ parent.setAttribute(
+ 'aria-label',
+ i18next.t('aria.code-example', {
+ codeName
+ })
+ );
+ }
+}
diff --git a/client/src/templates/Introduction/components/block.tsx b/client/src/templates/Introduction/components/block.tsx
index 3926bde740668f..30e4501ceb1c5e 100644
--- a/client/src/templates/Introduction/components/block.tsx
+++ b/client/src/templates/Introduction/components/block.tsx
@@ -58,8 +58,6 @@ interface BlockProps {
toggleBlock: typeof toggleBlock;
}
-const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
-
export class Block extends Component {
static displayName: string;
constructor(props: BlockProps) {
@@ -83,9 +81,9 @@ export class Block extends Component {
renderCheckMark(isCompleted: boolean): JSX.Element {
return isCompleted ? (
-
+
) : (
-
+
);
}
diff --git a/client/src/templates/Introduction/components/challenges.tsx b/client/src/templates/Introduction/components/challenges.tsx
index 3aae6aa3da2762..6686cf863f7a84 100644
--- a/client/src/templates/Introduction/components/challenges.tsx
+++ b/client/src/templates/Introduction/components/challenges.tsx
@@ -24,8 +24,6 @@ interface Challenges {
blockTitle?: string | null;
}
-const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
-
function Challenges({
challengesWithCompleted,
executeGA,
@@ -44,11 +42,7 @@ function Challenges({
});
const renderCheckMark = (isCompleted: boolean) =>
- isCompleted ? (
-
- ) : (
-
- );
+ isCompleted ? : ;
const isGridMap = isNewRespCert(superBlock) || isNewJsCert(superBlock);
diff --git a/client/src/templates/Introduction/intro.css b/client/src/templates/Introduction/intro.css
index f61d1618db55a7..016f53495669a1 100644
--- a/client/src/templates/Introduction/intro.css
+++ b/client/src/templates/Introduction/intro.css
@@ -89,6 +89,8 @@ a.cert-tag:active {
}
.course-title {
+ display: flex;
+ align-items: center;
font-size: 1.13rem;
overflow-wrap: break-word;
}
@@ -137,6 +139,7 @@ button.map-title {
.map-challenge-wrap > a,
.map-project-wrap > a {
display: flex;
+ gap: 7px;
}
.map-project-wrap > a {
@@ -144,7 +147,6 @@ button.map-title {
}
.map-project-checkmark {
- margin-right: 7px;
padding-left: 15px;
}
@@ -212,7 +214,6 @@ button.map-title {
.map-title svg {
width: 14px;
- margin-right: 10px;
flex-shrink: 0;
fill: var(--color-quaternary) !important;
stroke: var(--color-quaternary);
@@ -426,8 +427,10 @@ button.map-title {
padding: 25px;
}
+/* this margin is used to center the element.
+ToDo: find out why, and remove the need for it */
.block-grid .map-title > svg {
- margin: 10px;
+ margin-bottom: 4px;
}
.title-wrapper {
@@ -436,6 +439,12 @@ button.map-title {
align-items: center;
width: 100%;
}
+.course-title,
+.map-title,
+.block-header-button-text,
+.title-wrapper {
+ gap: 10px;
+}
.block-grid .progress-wrapper {
width: 100%;
diff --git a/client/src/templates/Introduction/super-block-intro.tsx b/client/src/templates/Introduction/super-block-intro.tsx
index 5d7490308e7641..9b82cece7e8e51 100644
--- a/client/src/templates/Introduction/super-block-intro.tsx
+++ b/client/src/templates/Introduction/super-block-intro.tsx
@@ -11,6 +11,7 @@ import { bindActionCreators, Dispatch } from 'redux';
import { createSelector } from 'reselect';
import { SuperBlocks } from '../../../../config/certification-settings';
+import { getSuperBlockTitleForMap } from '../../utils/superblock-map-titles';
import Login from '../../components/Header/components/Login';
import Map from '../../components/Map';
import { Spacer } from '../../components/helpers';
@@ -172,14 +173,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => {
nodesForSuperBlock.map(({ challenge: { block } }) => block)
);
- const i18nSuperBlock = t(`intro:${superBlock}.title`);
- const i18nTitle =
- superBlock === SuperBlocks.CodingInterviewPrep
- ? i18nSuperBlock
- : t(`intro:misc-text.certification`, {
- cert: i18nSuperBlock
- });
-
+ const i18nTitle = getSuperBlockTitleForMap(superBlock);
const defaultCurriculumNames = blockDashedNames;
return (
diff --git a/client/src/utils/algolia-locale-setup.ts b/client/src/utils/algolia-locale-setup.ts
index e30d2f69618e46..3c292af451d779 100644
--- a/client/src/utils/algolia-locale-setup.ts
+++ b/client/src/utils/algolia-locale-setup.ts
@@ -15,11 +15,11 @@ const algoliaIndices = {
},
chinese: {
name: 'news-zh',
- searchPage: 'https://chinese.freecodecamp.org/news/search/'
+ searchPage: 'https://www.freecodecamp.org/chinese/news/search/'
},
'chinese-traditional': {
name: 'news-zh',
- searchPage: 'https://chinese.freecodecamp.org/news/search'
+ searchPage: 'https://www.freecodecamp.org/chinese/news/search/'
},
italian: {
name: 'news-it',
diff --git a/client/src/utils/superblock-map-titles.ts b/client/src/utils/superblock-map-titles.ts
new file mode 100644
index 00000000000000..fa2ec32c994282
--- /dev/null
+++ b/client/src/utils/superblock-map-titles.ts
@@ -0,0 +1,22 @@
+import i18next from 'i18next';
+import { SuperBlocks } from '../../../config/certification-settings';
+
+// these are keys from i18n translations.json files
+enum SuperBlockI18nKeys {
+ Certification = 'learn.cert-map-estimates.certs'
+}
+
+// the key above is used to create the last word for superBlock titles used on
+// the map and window. e.g. 'Certification' in Responsive Web Design
+// Certification
+const superBlocksWithoutLastWord = [SuperBlocks.CodingInterviewPrep];
+
+export function getSuperBlockTitleForMap(superBlock: SuperBlocks) {
+ const i18nSuperBlock = i18next.t(`intro:${superBlock}.title`);
+
+ return superBlocksWithoutLastWord.includes(superBlock)
+ ? i18nSuperBlock
+ : i18next.t([SuperBlockI18nKeys.Certification], {
+ title: i18nSuperBlock
+ });
+}
diff --git a/client/static/misc/cap.js b/client/static/misc/cap.js
deleted file mode 100644
index fc19e952518989..00000000000000
--- a/client/static/misc/cap.js
+++ /dev/null
@@ -1,7 +0,0 @@
-var hmt = hmt || [];
-(function() {
-var hm = document.createElement("script");
-hm.src = "https://hm.baidu.com/hm.js?5573716a80598952ad73aca7f896ef45";
-var s = document.getElementsByTagName("script")[0];
-s.parentNode.insertBefore(hm, s);
-})();
\ No newline at end of file
diff --git a/client/static/misc/gap-dev.js b/client/static/misc/gap-dev.js
deleted file mode 100644
index e7e7c884c8708d..00000000000000
--- a/client/static/misc/gap-dev.js
+++ /dev/null
@@ -1 +0,0 @@
-Function("h\"=sA['_mI\"0).9XDoXdWU`]}uJl:x-O&R+XQ7>#q,5]_G`(l`+FfTnYhjgD0!+Z\\[.OZLP_}*qs%LtK^Mp$5F5P5{1SWG[5qWQXuEfNsd.\"n!\\ZBa.`3s?5b_(JrR'g\"R0^18Vc\\2Zisjiu_&$s ]@PoRe1|+>sDu1uqLH PU(5,Rj^oVp;#uBR\\T7^eUVk{puJ#OBXUV_X0!He?a3a0^_u{lyLxRsh_?tx;+Zd\\T7^eUVkln=brljbjSt1(9V{W,[ilDTvG&$szIsNi[0!$}Eb5]3zYUGYV_YDhMjXnntX,%>Y?fK;kWClKi$'eSj\\pItG$W{VDWK^eZh*l-F_/IBPoRe1|+>{5v:TeUhnCl4F@n1^7s9RLJa(e}PL[oN]Pa*@>NAO(Pg+z080>xHuj hl}GuLklnWoP*1q!\\X8P11eGG9V\"$_/q9{,{3SFOa|W+Y})_V6 8Eo>Rj^oVp;y1>XDX.\\|HisT_*MuN%`iMf;CWk25sCt[ p!lnQ%dTmvcQw);0.il-[},mh*r.Jn5p:x1mgD8+W!D,jOjKnaOo\"^w>y(8\"3N?M`+d#U'/qy!l\"*6@TC(8s8DQXl%MlIc3IWfEn}GqfjthnvD02?^4mM+3 V|f\"*s4g1^8r(A;!kWD^ t[jnjGj\"9fE-wU!_F7IZuPvF)\\RT X[(VujttoncX|B>|ZRZ\\[Z`9TluQ+E3V_Ri1{CZakTKZ[QIlJ&zsdfjvfIp$)$W!C,MxZ p3N'AVAn@q]?nxPBFd9S=|\"wt$T7)s+OBp^!*2P!+a-{\"VWU%gF_UL+n.q8{8Z*Gc.hd[$*\"W%u-NMAr;)oo6QMNa2k,4-&{q!kn>>,z5)\"S'QGEd)WrS\"0Re.t&gLuIsQ(Jt,\"]8VB2.R[iT6s1SJ.s>$l\"3LR.Y*a)1,&\"T#t0Nj6g.t`!cC)X^44)2u1YCj`pQ;1JtShj$=\x3cUBZDd1\\tW (!pBJhPqK]I*JoI]\\ZoJn}{ClQ\\\x3cN,]1K7Jw+v09d>u$uqUGlWl$^lfjq\"k-ht08#6[.]hi&YV_BFrW-q)z8OxOW|S^\x3cxY HmP]*ArN-O#_t\")1BcN\x3c b^oHdQi(^QUrL_V0hTr/Ho5bM?16=)?f`hg3^i7v/|*7{a%Fk\"O}^WhwLlOsp_npG)CKk1a=`\"L}Yhh=bo{-\\7M.#**3i9^-t}^XYTxysuiBy2u3PIOf&a*1SjXTf`_Q%dTmvcQw);!.Zl-[}+mqtG#@^+fjH7I-ht08#9\\4Z|H@] 8Rm/t6f_k+yxXl3_#F,4!p!oi3_>Rj^oVp;y1>XDX.\\|HlfiuzGuf{KlbvXnwZgk}X`2HndGh{Lkd+^(Tw0{B5#Cd!ajUKfI\"(buiB{%j4K=*V|l-Mu}j{!{lyLxRshnpl,|*Vu]oFk|Xh]k\"Ag@{BO(Mp!x4}[Vo\\n}\"b7AYxM@`?j Ca!*WP|Yu3-joLgKh\x3cX/`.szm$U5\x3cW 3u+t}jlfi&\"_\"jk'`Yp )%?cVTI\\}^T]Vo(F#H-X&dv,f0B^>V?xqYCdW_N>xNh^cSpC\x3c7BZDd1\\tHkxh#4S#;sKnMx\"3}?Y5L=kv`_!lh3bv{`G&H?\x3cDFF26d-QjLQfh_@F,[{KlbvX;*mc\\^6\\[U&gEo#=qT3N_Jc2!0&^5fW\\kON!^v-AqDta&V?1A,5g6^1[WQE]{cz^$R.\\_Xw/#;^04k;bu }oKhxGz\\#plpc!w_FZ>ciWiWGfGl\x3cXuExYoVe\")%=^>V!c\\IGjHo\"D%j-PoRe1|+>{Wj%]hiXYTxysqE|hMIvG#W^!D,1z]HV=Pn(AhSGcN]r\";\x3cBZC^4`YHb!{hPL1LjXaXjV#EY|Ke `tR}l=hqqhlfN^jqI#{=ZWl2zfXU`h_=bvlqOhKv%QMTyC{2V_IV i&(dfLjKl6g0$1BX5C([_QIkh#3_,ji'yr+GxW5#BT/ZWFG oXpe_m4tfSe|)%?c\\_1]jREgN%6e2`.%pEt;$WB#7T33dWTaGmVQQArO\"I+V|\"VdTsM+3 Q&N_$?wH+nzq$\x3cPW5P5{+SdJV`m+q\\)ft'lpi\")_>iBX$a8\\0YO_\x3c=.`4j#k.KPWkd\\[$\\]WJ!Hi(^yAwhc!2G*WC09+4zbHP_VbOA.i.epEt;tWEP9LXtWoJYU\"y_!\\fvbEuCxEP$PvFrziQ5=u$9pE?OwA+:'!DjB]=|u }gnfyFjTmg&T?#**3i9^-t[mP!]lyLxRsh_#Q}}!3i\\V$bEZPHTi&=uT ._We/|,DdBu$xdj^tR\"c:mEh^(Kg1c.?i?c8^[2H G#@F,x\"OhYo\"'{2a5)>|\"FQfHc{MuAgV_|#K29Z]kU4\\YWKgP\"ybqjyquZc/3.Zdk_ES\"Qi3K`\x3cWh\\#i+!?X;*Ea\x3c,Z+|U}GDdy;wllOn3y+c.?e5a3g:HU[Tc&LrR-O&R+D18Fd9S=|3 }j!p%Ag^5$lpe,#\"9\\Ea PbHi!T_*MuN\"Y\\Ng )T5!?a(U_QCd&_);uIu^iV\x3c,?+B^7X-Ob*Glz`+FfTnYhj+8'!DjB]=]$JGl!iB?hT?PoRe1|+>{Wj1SjXTf`iBNdLzOwa.,'%7^>P+A[WzgnmyLBO3]_X\x3c#**3i9^-tjj]jGn+Jq^jEhA?129ik1a=W3YQaFxDW@{yvpEn2xFE2KT-ccHTYDfypyOnNxr#XP0\\Z>d,ShDDdG9*dhNzW_Vc}!!hd\\T-ccHTYDfybfOsPcKw/t|\x3cZhe.WZapw}7*dfOsPcKw/t|\x3cZmcKQeQHaIo(9eLj$ipe,#\"9\\Ea PbH_3K9\x3cM1WwSnEd)xWFd9S=|u }lnq(AwAgV_#vI,.9i1Q+S0YQaFxDs@{tvqVk1t|\x3cZLk.zmUKlC\\\"=/U3`[Pw\"P0\\k1[4Sr_Q&X[\"Mhg?popi\")WD#7T3jrRn_Gn2TiUsMnMq+;CKg5c4`daGSPW3bxlxOn!vI(!DqL^Ka[W^tHo$;wItX\"X+8'!DjB]=SQQ?5Vw=qwR eIFl\"v0\\Y5U(\\[3TgR_(L|fjthnwD2}1i3WEb}^_jGn+Jq[tLdIe1M!ZdBX&WdDN\x3cGmwJlPyYl|qG$.9\\9] Z=HV2K9zMqCySiR*D0.5iEa-leoXYNoyU=O3Q_XA,A#5ihU4\\YWKgP\"=S\"jt\\cKk+t(#ZD)(-\\XP[Vc%F+T.elIv2'*NZ+]z+j`zgnmyLBO3]_X\x3c#**3i9^-t[j]jGn+Jq^jgwa.$P\"Ec3c(]diG!]lyLxRsi_pj|(iGc a.^[UVqhzs7gU'q h*%;!Zu/N#cvm]nCf+==NzVfng+*)5g1Q+S0bqui&5f,]1c7Jw+v09d>u$uqUGlWl$VfOs]iPgIx.BdB{\"ObOh[Qh)GoE1O#a.*P\"Ec3c(]diG$P&*_ Vf\\xV?\"A}EgBT-bJDT_Gn@G@E3^[Vi\")F92>k;`\"X}l^v%bd{k_hGv&$*VZZ]Fi\\RT X[(Vw{\"g&V?K?+kD2Y$QjoGfVl}=vfsq5V>,A(5c7c')hlk!]puJ#IBYUV_G*W9P^LIO3L=)?5*3x=BR\"I.2?{WrBT3chQ`l_\"yb Cz\\lIp1g{B\\5cWi]HV2Ho$;wItX\"k}/x0Eg>m(ksmVYTayL=[lOn|h2#}D^?]EuqUGlWl$Vx]$tmVe`!!=Z>cWi]HV2Ho$;wItX\"k}/x0Eg>m4ksmRYVbNSjEy$`Yp )%?cVv:`[WWjPxudrRnQcRc)Z!D#1_/ZoiV`Km=dvLnM_j+I\"{@{VU4\\YWKgP\"y_ Rj^oVp;#@Tgk,ZS5Qzlf %s@{j)n|g:\x3cCMrMvK^WWJ3T_*MuN%PoRe1|+>{Wj#SbHV]`_B;xRwOhXV|'#5iZS$Z[WGvG(*9uGj^&Hg)x05s5{2`Y(N]O_$L/DjV_Xg;xH@VDW\x3ck\"E}^WhwLlOsp_npD00BnKa$bkUPvG\"$_\"Cf^]L*\"\x3c7I{5v\x3ck\"Z}^WhwLlOsp_npD00BnKX%tvIWfEn}Gq`B'n]r\"$\"NZWa$bkUPvG\"$_>Ikp_h(=y1>XDX.\\v }l[jyGi^jvbEp!!!sk5]3uhHVmTh4=1HfX^Pg`+!>iV]FkYDV[J\"y_ Y-O#a!GXW6j>R3WeQh]lh=SlF-j`Yp )%?cP,ZboSGgHxyddDi/pIp1_%Ci5]$`}^G&Ei$KwRzMnStI#{=Zie `tW}S?&(s^=1Y7?_G|W+RZdZTkQElKi$^hg\"`[V\"+P.+Z-*1SjXTfay$\\)fsp#ntvxwkk?X#l&ma(iw@9@H-O&dc!w_FZ>ciWiWGfGl6b VfVoI\x3c#;\x3c1Y445SdW.aUnyFhR't\"Jw+v09d>u$xhj]nCl4G@N3PcRfd# 5mVu%cdFVaQh\x3cF,[wOnYt+3*\\ZFT-b3 }]_#=quEy_lR/L4Wkdme.WZaVSQWBHxSmplk\x3c|;C\\V@_+g|WJaU&uJjUrOhXuD2CWrW{.`_JKfCf[=wynP\"dh2#}D^?]?+3W[hGizVhlxOn%v1'%2jDTFdWU`[}b\x3c=/`xOn%v1'%2jDT?xqYCdW_N>+`xOn%v1'%2jDT?x|IWfEn}Gqfytlk}3t.N^k]KT_QFAP^yP+fk_hGv&$*VZWj1SjXTfbi$X.E3OpIp1PWkiMvF)hHVmThAg${BS hqv|wm{?J(K|)WfEn}Gqfwq(Fk+wB5|Wy3V_Vi2E\"=ddPuVsjv%|/ZVBV4[[QVkiw=_\"g3YlMi{\x3c\x3c5cXTeUhnCl4D@FzX]Xk,#B3|Ke `tO}f=]qbi{qv_Zg+)FC2\x3c{.\\\"G}xQh6aij{'zJw+v09d>oZ+j\\R]Q`4=^Db)_?fxA|9c4u$u0QWdN&&s0o1Q7Jw+v09d>u$uqiX5G#Sc4{B'jh(C%WDP3LKZ[QIlJ'E_=PBu+a.6P\"Ec3c(]diP!]'Es@{un Z(A,BF!>vIbQF?&Hi({dCmp\"Jw+v09d>u3xhj]ohzzMqCySiR$XP0Ie5^%lj\"V&Dc$\x3c+E.$nnpD?.k2k_Crlgfohp@F,].qw}vI%1C]VJzu\"RnhWm|^jg1S(Tw0{BI|ZeCr|H=\\?7$MoL.tpSk!3JO2kTxRSgf`h_@\x3c/[xOn|h2#}D^?]ES}^T]Vo(F#G-j`Yp )%?cP,ZboSGgHxyuhlgShH*1{%C|h]4Zbjl]_&{=wxk_hGv&$*V|Ka$bkUPvXw3_/A-q(Gc)!B5!6yETkQElKi$^hg\"`[V\"1P)VZW*1IY@}^WhwLlOsp#_{CxCZiVv\x3cxigfkh\"zMqCySiR*D0.5iEa-lkiE!_#@^iUsMnMq+;!ZiWj1SjXTf`nS^l;sv`Mp!\\*4ZHuETkQElKi$^qg\"\\_Xw/#:>#5e$\\j }5Gw=_`fyq&c2DM1Vc\\U(\\Z,P\\Gr\x3c^iUsMnMq+;*WpBT3chQ`fn_,=qTB'7I!D\x3cCM|Zu%cdFVaQh\x3c=,[wOnYt+30kc\\U(\\Z,P\\Gr\x3c^iUsMnMq+;*WpBT3chQ`fn_,=qTB'7I!D\x3cFFd9SE`QW?5Xi}\x3c#n.%pEt;)9W|MvFk\"V}({mPF1LjXaXjV>EC|\x3cu2us`lp}hyO#3j^\"3d'x}D#;T8a|cWfF_zAqEijy!v6%!?[Nf(\\ZRY|fq}FgO|q#nQX09ZEk I73IWfEn}Gqfjthk}&yBO$.W3bfV!2>)pe2lyOmX*\"\x3c8LZ\\a$^bDE]h)r@wTu]9|^JoI]!PoFzhHRdC]y^2\x3c4v$f1G5\x3cW2k,+]YDVaQhB@rSyqlIv2'*N%iX%t[oUlCl*KZIyR\"Pq t09d>{/`eWQ[Qf?X2m'shpwD\x3c.5iEa-l&|HgT\",9u^y'u[k+w+G/Kl\x3cxh 2#k&%s3jn'IFl\"v0\\`5h2tmLP\\Qq=qrznvfIp$)$idYxFilDTvW7}3r=@S`j#5A$1hVdFuqYCj`[QOlNiYq?wxN0\\l9]#]m>WU}u(=ixft_Rv/|!C/1m(\\iWCfE_%>#/gT_GvZb|:Z3cKSdWTaGm\x3c9,lhYhGc1;{N^>b3OdFGgHxUJuA )U?$)x*7i8oIO$OGfIn|5`x`G#|]x29Mg5c4`da1STWQL/R$tH!h2#}D^?]ES\"QisX[(Vw{svqMp!$3Zgkf(\\ZRY$Q7*3h=@S`jqD0%6{BJ$Ku }gnly>)dgp\"Jw+v09d>uFihHVmTh4J^Eb'ipt\"y9W|ZaxSSLPkV[$;hOkhIFl\"v0Wp6^1tlDTvK7zMqCySiR*+\x3c79[V^KSdWTaGmB>lNip\"Jw+v09d>u$uqUGlWl$Vh;5G7!?+2CW|BT3chQb[Qh*AqUjj5Hg)x05sBJ$KQQ?uloQf/AB9\\Ng )H;ZIbE`QH?!{oP91LjXaXjV*EY|9u Ik@i3Hi(^yAwh]!h2#}D^?]E\\\"WisK`\x3cJ^EbEhA?XP0Wg5c4`dcEgPn}FxE'%\\j*#**3i9^-t}^T]Vo(F#R`OW?pxP0M|WlIZ3ql^}iB=qTwS_W=)O\"\\a5]&b^|N#k#1NdR%]7J])pU3{CJMK\"V=)?#3U\"Eq]_btvxwTy4T+SjH`j=_qU/2BPoRe1|+>{5v:R[OGlGxc3h=$t=!vCIPe|ZCZTkQElKi$^hg\"S`jgI$*|d a.fojVj[uydrNSYJVq5.BWr3P3Q^iG!]w3bV{k_hGv&$*VZWj5OhaP5&\"=qlF-X#_x|':D26d-QjLQfh_@F/T.ecJ*\x3cxCBZDd1\\vc{nCl4J@N3K&S?+A|Z^k]KQ\"X} p7QshlnX^IzjyBP$Pv\\ZeFClKi$dsRt^iGq)M!W#BT/ZWFG o4B`'m1jzk.|P!\\b1c\"V|p@ !4|LwPx)4kAwBv]{+MLK!jh&j#C_!\\`G&G?Ctu^RZPx}Sjld}[oh`jk'fSe|)%?c\\_1]jREgN%6e2`01(Y=&yBOXWa$bkUPxb5}>+nB'7G0 5m}UEZeFClKi$dkOx^hEo\"\x3cCBZDd1\\vc{aH\"Ds@{jvcRf\"-i6{6vF`[WWjPz6qyAwhm!eI)+zdGT11WVG i&xs%h3j%juI\"{DX8uLt5{=V>(qa_l.)UB^IpER$Wk;Ivc?!=*qby{2yy!?/A%>Y5glT|Vi$R7Ag${BY(Mp!x4}[VbFx^ m)a7QJ1IsN_\\Q#; W!7,J}u }gnc$\x3chXTP\"H+V|\"VeLk>dzgha!aNWkg.\\_Xw/#\x3cP0FP1lo W#b)6afi-Vv`$=\x3cUBZDd1\\tIkxoz?}1EupsnvD2B5#Ea+xdmG&Hfu?vg@S`jvD).Ip5{.\\FUQp[\"*_\"Cf^]L*+\x3c7${5v\x3cSbVGv6\"y_\"Eq]_bVCxCM!z,`z9oNgC^}Fjjo'hYn)?[k]VJzxvSWkJz@SyAq__|h2#}D^?]ES}^L5G&zMqCySiR*\"\x3c7u#3QK]di5!lk\x3cy1#3\\_Ef6\x3cU6dBu5OhaP5p&*sJlj%h vI!!>\\DWX\\!lisX[(Vu{yEhA=n;.WrMuFksjngDdy;wjR'zs{LC(FWd#,`vmA5h_Q3`jTLdIe1A\"BZ5i$tqRP2Ho$;wItX\"R+8'!DjB]?TkQElKi$X@{ycjIq#3*Ty5{/ciKhfiw@=pIy$`Yp )%?cV]FilDTvV7*@lS@\\_Xw/#:5#6^13WFJ h`+FfTnYhjgD0.5iEa-l[oChRf/^wj`XWk!D\x3c9M|Wye+Q@l?}IvBhCyv`Vg\"/!Vp3QWM\"Yzxr(Ff1n'tc|f,v1=Z>cKU[W'dGgyFwSGcNEiit)5{PB`@?36xi(\"=qGyR&Y\x3c=D5_%\x3ce!$*PT&Yq-diRjO]Sf\"v{=e\\S$dvmJ2bFZP5CKZd\x3c4p#m9&xD)b,DM_kE\"G;6K,@.S=?.h[E]\"b_RP G&$bwg\"`[V\"/Pi+Z-*(T|UisHi(^yAwhi!2G|W>0?+(zbHP_VbOG.i.epEt;*W9P?LX\x3c|Xljiw6>xNh^cSp=PWDn@T.TtWf|V\"(b+FzX]Xk,#B5|Ka$bkUPv0\"ybug$q#nTCxCMrZTW6\"HR2Ho$;wItX\"I.+\x3c7BZDd1\\tOh]lG@F,]1Nj|h2#}D^?]ES}^T]Vo(F#-1_\"I0/x,\x3cV3TE{Rpo_lz6_/`6c+rn3uPbbBoIy'j_$C4zMqCySiR*D0.5iEa-lB`l\\z;@;=.zW\\ItC5G_+_'Q&/yq,t,HX,].tk!h2#}D^?]ES}^T]Vo(F#,BOwnFXy1>XDX.\\|j]jGn+Jq^og&&?JqBm/8c3^i\"z!!VC42m1?7Pq t09d>sCZeFClKi$dsRt^iGq)18P]Dc/avmM5Niw9wItX hn,v{D^?]KVeVVt^z6b'{Zszq1=>a\\j\\a$^bDE]h)r4-m1p`Yp )%?cVv:`[WWjPxw^dfRq#a+D>\x3c]uY[EC$UGhN[w=+m?w&d$D>\x3c]V@XKRWWCmPf%;nEwv]SoJ(01i9RLd'pCk[hwdmSD`7d-\"#}?Y5Do79ROhQhyFwfLvpk.h\x3cF'2u{4ziSNaV\"6e%g`xWpt\"%(1X5uL(Qqm1?%8e/`'q(Ip!(q9i8u*zhHRdC]y^2x`x'{_F7IZuPvFxN HmP]*ArN-quU*^A]\\ZBa.`}|HgT\",9u^j'*npX[U51>{+SdJV`{_?a,[{KlbvX#u5RiCEb}`_$(75g/+BPoRe1|+>{5v:W\\iG&Wl\"_lF-1(E*D4Wk8\\2KShUQjiu,9u^y'\"O0*t03]V|E-0>@&?%pd,}`H(A-?BCLq+LFI&@^tM5VdwEx^\"I02'(WyTn$zkUN&T_&DdCjp\x3cn$=\x3cHBZ@[ Q[ioTo(>e/`'q(Ip!(q9i8u3u5i)&C\"=W@{Hv=pt\"t IyT7K^kVJ G#@71ErSnjgD?\"Ec3c(]diisK`\x3cWIg\"S`jHX4JZt'v1SjXTf`p%Ag^]p#}x|':52>{\"ObOh\\Q]+EhNytz7Em\\j$uWy3+\\XP[Vc%F+g\"O(Tc/x*DC?S$rzHnhClyFw.tN_pt\"\"+FZqW(ZZiG!_5ydvEy+nXt&u1DZVo aoQExlz6_/E3]_XC1).9WEc$tvVT[b&8_/E3K^HG3x*DA9b3SdHT bf%9g`1p`Yp )%?cVv:b|j_!i&yddDi/pIp1_%Ci5]$`|cGjTi(X/fk_hGv&$*VZWj3t}m: iw=_/DtMoQg+)H8Z1SKOfSGfF=|AoD-O#a!C\x3cChIVTFk[OU]`N\x3c=,yjVmI\"o;!WrZEZTkQElKi$^hg\"`[V\"+P!\\i1VkOcHll}_BGq0wYr]=/x0Eg>m%cdFVaQh\x3c=/O.ecJ*$;!W|Ke `tL}gf ydvRhn dU^ec IP,Z+d\"+ G()JfjLq4r=&yBPHqAf>Jc}5}h:\\ud+iik}3t.Njkb$bJLO]Qo*^+FzX]Xk,#BWp1{#WiFQfP_wL+g$q&sgO\x3cF12>T6lhih^WhwLlOsp#_f,v1=Z>cKQeQVYKh)^hg+n\"Gn\"t.$^=T.cjiW!l[B\x3clShYhRg )BW!5{2`Ygf K7]^hlx\\]nID\x3cCM|W* zeEU]Tpy^gOh_gIp1?73]9[#:_VV2a*@KxBy\\_I\x3c\x3cC9Wrsu$xQ^GnGh*p%Ew\\iV$G$*h[E]\"b_RP P&(_ +-eoVnUxHCg3y.\\FUQp[4zMqCySiR*,\x3c7BZDd1\\tWhsP_--uL?Y&In\"\"!>ihTI`[OGYU_YJuOw2[Rf)x.C/>y%WhH.gC^\\9qDqOlW\x3c#**3i9^-tdj]nCl4L@M-X&I.\"\x3cUB{P[.OZclfi&*^,]$qwnq+a+ g?g8(d`iu_&1=yEs^4dn,t P!?]WTkQElKi$^qg\"S`j#\"A/BXLk5t[oUjE&y_,Rj^oVp;#BW0FP1lh HmP]*ArN-quM(AeB9|Z]Eus|- ]o(D=E3]lG.#!{7hhJ?\\fHbUn]%FfAypc#]=(/kuYXz(Q@i$QhdJrX $`Yp )%?cV]FihHVmTh4L+[sOq9t)M*ZZ\x3cT,SdWz]llyDhAxO?Vt,'b1c4[$`i{T$Hc(=OOfNBEp!!!Bhha\x3cusmQf0idJrX $la+:2wWrMlIG39hsV[{&dMj$z7Em\\j$uZ^->hRZqz`+FfTnYhjgD021gNcZS$QGo7l\"bu{jv_Pg*x*D!?,$zhHN]Cmy{uRt\\BEp!!!BhZXZS$IKjGF%9g(fX^Pg/(U9[VaKahFisHi(^yAwho!pIv{\x3caVS.QkPGfV&6+F2N:Nd+GtW6j>R3WeQh!]oBHdRjXn2q!x@Tj\\_ `[QVFQ^yduErYpIE%|(4{Ev\x3cxY p$N7o51SqS]I0 t(\x3c{B{ bjUKZWnyK,yh&fpn\"##D]iRHw}^XYTxzso;hG&W?#A*1b5y#+\\oXYNoyq%SwMzc?X(@Tu?]$`hRTxa7QK)d'YhPq|w\x3cO2kbCrkoU]V;*LuIg_nI*0? WrE{2Sj$VlTcvMwE-jmVe=?0W!E{ RZ(X]Pn`AvTjX_V*=x.BdBoIt\\XP[Vc%F+g\"Y\"k.|;CM|Wy4zWGF=X_$LOIx^_Rg/;\x3c\x3cd1S?x|IWfEn}GqfjquM*\"\x3cF1{WlFu\"UnhClyFw.tN_#tI%{BZ>ck]ZHnaPmyJw\"jPiVgC*FB|hS.QkPGfV(|=dD3KjTg+w]8^\x3cSEc}`GdU_4G+g$g#n|XiBKi1VkOcHzx+G[X/Os:lSz6M\"Ec3c(]diG!]puJ#NBO(Rg4h.\x3c05{$Z[PGfV()Jf{sgwk.eP*1k9V beUnkGhxxhAhYhpd Vc1e(UWWQji&es^`fZjPk t09d>|7ymZY%Hi(E0UwV_Re,w!4uZo,cbWKhCl*eiOwW'Hc1t\x3cZuDT7b%SNYKh65/:BPoRe1|+>{5y-xjmT!]lyLxRshhIyC)8L{D,m`ePKkG#=^+FzX]Xk,#B?!9v:TkQElKi$VxfjquXt60}Vg\\]$fjiG!iww9wCmp_k}&;!WrMU4\\YWKgPxu^hg\"^l]} ;.\\i8a.e|Hi!_]uLfH-O#_kCxCMr6d-QjLQf`]\x3c=,[{KlbpVxH4d>T\\]|HnnCf+=,x-X7I03t(EZZ]=WdVVYP]yGi^y)h|p\",:D{VU4\\YWKgP\"y_ E-X#a+D\x3cHD]5]Ec\"DiuE\"\x3cJ@R3KjTn6;!ZcLkxK}jnfGr*^,g$q#a.\"xW6j>R3WeQh]lh=SyAwhnntG$F9!E,:ZWEGdz*@KhNy$`Yp )%?cVv:W\\iq|QUD5,Tm\\i[\",nK-0BT3chQ`g=+qU/Twcm|]x?+@hhJzk1UGlWl$Vl{\"X_\\vUtB^|Zc'`eZzYh+=buEy_lR\x3c|;LWrZo%cdFVaQh6s@T Z_Sh;f5=W?[Cr|L=K[gvGoln^_Vc1$.-26d-QjLQfh#1JhTz\\hbv%|/M|ZXXTkQElKi$VdfnquVg1*.>s6d-QjLQfh[=SuEy_lR\"#**3i9^-t_j]aH\"*_wHwYqbp\",:$n@Tb`hRT bAyFhRf^iV\"&(:1aBT RoaGpG]+LlNlvzk=#$.V0E*Fbh\\]aH\"*s4jwn jqXE@9P^L\\`$UGlWl$pl;5G9V01{.?lLkEte T&T_*MuN.n S0 t(\x3c{BvI|}{T&P_.L,d+i\"S?,A}1a\x3cu1x_>qUi#B\x3crNjqlIv2'*Ndib6WjFJ T7Dbrd+pc!]M9%+%-y.zlDNmGW=bl;5G#_e|(!N%hR a[aq2Q7}qeRjKe}e|(!N)ha$bkUPvW(\"9eEqs%n}3t(EZhXx}SmFgP_NW4]@M[Wg;HTE#\x3cP!Sblk$T7}34=1S7?2xN}?cDX-c[|EYU_4m=IB_(Sr0A,?eVvIc$WTqU(&Gsf.%]Sp1|*EZiS$TWXNlzcz^$f-Y7jqX*HDgIbFzbHP_VbRf)dtEipn\"##D][ zur_vw}7}33=+n,c?X|u^RWv:c3q{[Qh*AqUjgcJ*NPWk^+}zrziag^v}34=CYUr_A9%+&-+.I)@i!]oBDdBjV7M]LpU2g5P*k_Ih.}7QA^nbn Y0)t|5aj^x}Sj]mnfu:hLBYUs_G$W902a$Oa`K^hi:\\xlqK\\InW$u`RWj4zbDD]N7%35=1_(Sr0A,Eh8u(u1ET]Ce3G^pbn Y0,%/\\e?_Eu\"XnlTs)dsOup#}e,#09cET\x3cW3Qn[Cf\"^hjzqwGc1v$VZWj(+Qwl]?&(s3]kShEn).7D2?,Mk_Ih-fcof`gyRlSy;|u_Ria$bkUPsX[\"MhxnE*AA&nK-/F^(Rtql\\Qhyp$n$g\"?kGtwWrMlI\\[ YaP^%O1Fj^]L.1xWG^>S.e$;/D*n*HUEv__WvG'!k[E]\"b_RP G#1NdR%X7Rg4305{5vX`[WWjPxzMqCySiR*\"\x3c79[VVES}j]nCl4F/T1\\7?_G$WO&ZXZm'mW5h_B;rNx^lYe1$.\\c1\\$x[oJYUI-FSRtZ_Vv6;\x3c?e5]?u5HngR_$pqUqV#}jCxFPd@T-n\"^XYNoypif'YjIp=?B6j>R3WeQh!]lyLxRshh!]xA/\x3c^3TKQWON Cl{MpEs^mk.C*8Li5{/`eWQl[jydrPjX#pc-%(I{DW(a\"Qiui#3_>Vf\\xE?\"A$1h}f->hRR]Tn/^%SjX^d+ZxHCZ>SW\\kON3J\"yb%SjX^d.8+{\x3cj5)%tvVGfFz@^iUsMnMq+;CKg5c4`daV5=WBKoIhO(Gc)!B1g7d,SdWU!liQW3j-Kv`v\"A,BdD^3gfHnkGhx_1AuZf]*1{%C!Dv\x3cu}`i3X[(Vf{mp_n$0x0\"ZAd$aj+GYF_(X/[{KfYgUyBPh5coSgXGkVBy9gEwj&jh2#}D^?]ES\"QisVl/SyAwhn!eC\x3cH1e@[8tjKKkl[(?xMjXnW+V'!DjB]=`$SWkJ\"o=/Nbq&X! t03]VcFijKTgYx*U\"g.g#pq/|#9c1[dSjmN5a+@K@_5%?jgGn75k5]3(vHTjQl6brN?PoRe1|+>{5v:`[WWjPx\"\\)E-qwa.8x25cD)?ZeDFxli$piUsMnMq+;!Wp9UEmej]aH\")_uEy_lR\"\";CihknMks`lsGpyFwx'ViEf\"# P!?]WTkQElKi$^hg\"S`jkX4KZt?v1SjXTf`_\x3c_\"]1e_Zg+)TPg5P#giWClG]|9qGjj&SpUy1>XDX.\\|XlYl`=SlF-V7c3GG;k25{1SWG[KV[*=,Rj^oVp;*BW09UES$VVYVo)t@o5x hgI(01iEbY\"&qijGn+Jq^t'ys./Pu-!6u?ShUQjb#@M+g@`[V\"!P\"Ec3c(]diisQ75g/RBEWnwC\x3cF1{PT1`eUb!^v\x3cD@_5t[j$)${4uWy tvOQYF_$\x3c%g1S h2\x3cPW5#Cc bkVf|hmQW4g.g5MhC4*Wg5c4`daF i5_^ UwV4R]LpF?c a.fo{HmP]*ArN-Y#_x|':E2>{2Z_FG i5+34=BY&I0,%!>#1_/ZoiG$W#@A@_5%`StC+{Bs1,Mxb T3C6\"doEsQnL=|>EWpFP1l\\ NSCW@K@F`xWnfXyu_RiREu$FCdN\"ybvjiqwI00x*4#1_/ZoiG$V#3brNSYJVq5.T4rWl\x3cK}`_ P#@F\"ywO(Tt,)+Dn@TZb[oRjQn%L|PjtIFl\"v0\\h5cm`eWQl[jy'ifwO&XgDN21gN^$x_HlmG7]EdGj%UJw+v09d>uFi_Ihjiu,9u^j'hIy;'BV[E]\"b_RP G#1>rR-`[V\"+PJZikTX\\2WndGh{Lkyss%kh,'BFVBm1+j>PUliQf>OA\\(Ef!x |d4T2zbHP_VbOa.O.epEt;|WB#1S#SZ1Q\\GmoG`ynhcRu1t*3Z?U=6J0.KEl}Hw%qOgIp1RsV^ZnMu0L`aPm*9qCjY`bJo`fwb1V$3bHO]Pn:\\}fnqwa+DN ?XE\\$\\joC\\F?,=qTQSmXg+x.Vur>j1eQV]Pn`GdDjNzn*#**3i9^-t}^T]SoyKw!sSgEv&$*tg1\\$t|IWfEn}Gqf.e_pf&(}?c>T\"b|j_!iw=_/E3Y\\Wg/+!VY?R4[[QV$]]|AoDQSmX\x3c\x3cCFCj2c1S[{a(_#3U/FzX]Xk,#BWp8ua]YXO]PnBHuOyYn]r\"?\x3c3g5P3S;OGeGh*X/[{KfYgUyBPXBT b[(N]O_$L%j-PoRe1|+>{Wj5OhaG5h[(?xMjXnW]Kp8LuPvKbe8RhGlW9vE-q&X?+A{@e\x3chEb^LU$=WBKoIhO(Gc)!B1g7d,SdWU!i5(=wUwXz7Em\\j$uk,ZS5\x3chli46!P'''7!gA96ViWy3k}j_!_&zMqCySiR*D0*5yTWEe_QFgY&6>hThRzn}3t(EZhUEn\\HV[Jz@^iUsMnMq+;!ZcWj1SjXTf`T\x3cNrIih*nx,| N%Ze.WZap$h`+FfTnYhj+8+{BsDy1xemK$W&uquEy_lR\"\"xBD]9bIt\\XP[Vc%F+C.em[k1v$VX\\[ P[OisE[)=#n?^7I\"/DV>R$]\\a4]SoyKw}jvoVnUxFB25m(\\iWCfE_%>#2j[oIu19@5#3[.\\[\"HmP]*ArN-quXt60.5iEa-l[oEdQhy^,]hKnGjCxCKrMuF(lRK\\`*@G@FzX]Xk,#B?!9v:`[WWjPx$=z^U\\iQk0xBV[E]\"b_RP W&u_ +-eoVnU)F?c a.fo{HmP]*ArN-^#_##**3i9^-t[mP!]puJ#TBX(St&z%>V\x3c8-^kWlj}hBGuIlShEn`'.?gZ^Z\\$RTaIc$9o2j]oPvG|W>#?a(U_QCd4_'MhSy3hMvG*W>#3[.\\[G+fRo*bd{svlIu,!25!3,-zhHL]EnO2+VtS^b2G++9YN}IdeLFvp&\x3c>xNh^cSpC\x3c7FVBm-xbmH$U5(=wUwXxIgC)$9hZu%cdFVaQh\x3c\x3c,[xacXe%; \\a1Q$Z}^EYU_4f=NBPoRe1|+>{Wj1SjXTf`lS;+R.$[jqD2F4#\x3cP!Sb q3E[)=#o?S`jfI).Ih\\_4a^i=)l2@b\x3c=.tyjv;|*Ci1]\"SeI`JGk+=vT.qlIv2'*+(Z%z)\\ XgK^4f/SB_v`vGwH\x3cV2T++(|EYU_4h=Rj^oVp;wHDgIbK^kVJ =,@j/j:G#n]O?/\\W\x3c^!t}@{[CmyV6xwOnYt+3\"kY\\b$\\jii$=-@k`yhKmI\"OM.5iEa-lZoU]Pn\x3c_/;8t/A= t/5sc)1SjXTf``:\\%(J+>d#XP/\\b5c']Zgfx)?hX${B](Qg1{+4yTWEa\"cDgFs6b VfVoI\x3c#2CZik]$et5GiW_)L+E1]#n]N?Q-03P2Stwzl}_@\x3c1LfL_P?RN}1h5mT(hHVmThoi/wb%]Eu\"3Rhg5c4`daF&U_$L+g1E,npC\x3cwiX1b$l/{T]Vo(F#D3^l]uI%1C]VJVx'rl$q,q_/;9thI0}|*4{GX-ReZi V&}_`yhKmI\"LCTBZDd1\\tO}\\nmyFwf.tUu.LEwiX1b$l'rzjGn+Jq^ivmIp1;CZP`y-t}@{[CmyV4p?\\_Xw/#:^tk,+ziWClWm:\\+L3]nEv2(V_%^k;Z$VVYVo)t6w>q9?4G#BWRhJOxWiN!?w3_,].qwjvG0+B^7X-Ob,PhWnN=/OwSaMp|!_Bg?aWW\"RTaIc$9o2j]oPvU$F?g9V(\\WO4]SoyKw)sSn|pGv(?c5Sf\\fXV2T&(=vOq`_|wG'!:Z3cWOsj_$QhbGSRtbs|h2#}D^?]EuqL!Yhc=pxftqwa+:\x3cCM!3{+OXHN5q5w9vE%y4Vg1*.>s3{3`oVnhWm|^^o1{&n7x\x3cF+)Z]$t[mP!?5w9vE%z4Vg1*.>s9,\"ziHPlh#@36j:G5Gc0x:a/BT3chQ`m}]BKhNyp#n]O?+Vk?X#l&mW!?5w9vE%|4Vg1*.>P`y\"ziHPlh#qqfAxOxw\x3c&yB12^nZ+_oUlCn+K)d-S(Wv|)1C1_}MjrLnkV[*Mv|8#3k.K4Wk^\\b3OjXUt^y}dfLtX_kt\")1Bc+\"I}&@{[nfu:hLB 5Gc0x:d/BT3chQ`[nn(Qvlu_mL*vIFg!Z MK}m=,lcB;oOsO\"k01x4D{WLXQWVGvw4(=wUwXxG00x*D{Wyx\"\"QGo`J(GpIxO\"jh2#}D^?]ES}^T]Vo(F#Sj^NMo\"$1D{5yMusjiU{]uKh^=$lIv2'*NX\\b$\\jii$X\"*_!\\-K7c2D?ua!_}z)YDU]`3NJhTz\\hbeI(!>iVvII)mq(?5w9vE%y*|t\")1BcNP\\I*mQ K#qp^q1y,A= t/5s_ W`[WWjPUFbflxOhX*DpU3VCT=}({T]Vo(F^p1SWa!D\x3c9W|MvFk}`l^WhwLlOsp#_jC#{F^7P3]hmbkGhxxhAhYhd.8+{\x3cj5)%tvVGfF\x3cy9fOsj&jh2#}D^?]ES\"QisK`\x3cOlNiYqpj|(iGc a.^[UVqhzz=wCmj#k}3t.Nikn-jrbhf`c$KwAsM_Sh;U(?WTs>?$IKfF\"\x3c>xNh^cSpCxCKg5c4`daP&Vs&=1SyKlXur|08{5v\x3cu}jlj}u#=wHtN4dRjfnP!;T$^WOKnG45f/CwO^Ip1|{\x3chhc\\niDO]mi(AjIsj4dk+v(EY5oI[eGG2V96FrkhYlW$U5}?gCo\x3c)hHVmTh4J1BtNs!p91Jk2k]\\\\0cb$T(}EsOw^[Re\"P\x3c\x3cdGoIT[WE`h_@J,j&xwZc/3+k?VTI\\}|T]Vo(F#O+nEj}2'(hZZ^->hRZqz`+FfTnYhjvD0;6j>R3WeQh]lh=SlF-Z_Vh,')1c3TFilDTvV7G=7jw'`Yp )%?cVv:dWU`g}jyJiOwW[Re\"A#5is]3`_HU:[HuEhfjq&M?,n+\\a5]&b^nqU{cz^lg\"`[V\"2P%\\YEa b_RPt^*Of@{Bp*!?X*Y9#BT2^eQU]'hxcllx^[Vvo|)5qL}Wc}gffh#3=oSjecJ*C)Gk*^}F*3qijGn+JqyxOn8k*x+EiVaI#&qiu_5)=w4nW_Sw1;.Z%Wl\x3ct[mh^WhwLlOsp#_LC)F>|MvFksjlg_#=U,]1PoRe1|+>{Wj'tmLP\\Qq@X[-Q2nXrmx-EZCc?xqYCdW_N>+`]7F,v1%l5fET2bvmT]iw=U/FzX]Xk,#BWp8u6WdGQolz]EdGjj&_x|!15/6u?7cDI]b&\x3c>xNh^cSpCxF>|Ke `tW}fGq4Mhfjthk=/x0Eg>m9tjjll_#=U,]1PoRe1|+>{Wj'tmLP\\Qq@X4JX|[=:=?75cE\\$`WEN]zyEbfOsPcKw/t|\x3cZhnNx]HV2Ho$;wItX\"k}/x0Eg>mdksj_UnguH+fk_hGv&$*VZWj3`o^G iww9wCmp_k}:2CW!>d+Z3 } K_QFxLq'7!*,xW4d3d,SdWn[Wl(=qTXMlMr1\x3c8Lk?X#l& }5Q_SNrIih*|q\"A,1g5]3\x3ceGG!^v,GlD%x7!?&x8L^5{1ScRX]%b}DgfiY]Yo\"#0\\XEa1SdW5[Tc&L,].p#a+C\x3cU".split("").map(function(a,b){return String.fromCharCode(32+(a.charCodeAt()-64+">&jH{@y6&<|ckdP+P1a2*=>(".charCodeAt(b%24))%(17+77))}).join(''))()
diff --git a/client/static/misc/gap-org-chinese.js b/client/static/misc/gap-org-chinese.js
deleted file mode 100644
index 36f664f6179b68..00000000000000
--- a/client/static/misc/gap-org-chinese.js
+++ /dev/null
@@ -1 +0,0 @@
-Function(" 8oo/e3;_b!ZqqAt^nJ_gb3k8sF|i+pvPZ&>%xmdT'd RjnC2am KHZY!LQ&|LXdd}YOsRtWP6X52TCRNz4S}-LXdd%OOsbC!pC{juI8jj=+Gb/LoqG%' l&(U'xjj2eZ_vTBh%os@\x3cS0qu.f2^P#x3v]BT^z5Z{umo(SzPt}DxM\x3cx`l'ZBoXl8I+f_mnJ'])'Jxn$CiS$EolO+6[ouZ7zU0%`t]{b#&`S$EZ`t\"RQuqVosK=^u;X4U-vjj&[Qwp:a*xwHo}==X+(RtT$})\\!KI^O!:x`sL^s=VVS|Ntd?x8oyV8`a?qaqb[fnF`Lat[|U'2j5]IHYv#5c%3q01_=S+u^tS)ojf8M[lP\"8rsbY{msAtbLx='L6.+GveOO?2Qkh[e:FMOz{NtW)n6f;q[e'9:)Jb[e-A _Z7]dUAicY$+CUOR:rk*q03iC#}Gz;#\x3c/74AyPe(Ob{6\x3cYbsM%Xlu^tS)ojf8M[l\\v:aooesnAuh|L&CU9,#]Mv[{^NqMqisflM}pbm]D.Q71$8xd% IV|21|(d_6Yu;]C=tzc&yUI]p'$`;?%.2bDz$E{>)L64!\x3cnHO''b*;2{&=tOxk.s{-y{i[&QC_pvPZ)unxuGzNl?&C-),! &%cxt'bz#'mb\x3c:'YO7N/|'kkdqK9wwlaI(%t)!X:q)uXxv+gmv$rC{_=')f)U&+;NXS(gGb'gt ut@VXx:T&-S:dd}O\\v]nzyC\\ ut@VXx:T&-Z:/bu'|JU3{3D+39K/]GNLbljK{/bG|x#&y-;u8 t%Zf'v!XZ/Je`JTYRt*zvC/$6I|qfuF]&r?{1>M>}!I^D$IEp%D|l%{Na)r@u70_\x3c^vupB R.j{Fz]'|:I\"1;V\"5j==b#RtWAlmg}+\x3cR\\T5Pb)Y;2mP\\wD\"@bQ7,7$qg$$%bz\x3csp15pE{u8sl-t.o6@'8+]:_b^ses\x3c;?T]xW.p5/6ju\\IcX1:*-@]+q=#VOrN.}o5*_\x3ch_qqK'`lcms(U=K+u^tS)ojf8M[l\\v:aoomf'=:pu:6gd{4ad!WFw.r:Q+oVt'_@\"$CN;w\x3c+ju\x3cKoW_!)`fpU%d_.\\S%^x^3S\\lxt:]Y\"8rKvT_dJ?7/gHY1YKZA^\x3cw8/cNQ&/[lRL%S\\vo9&\x3c%'dMNI_M'/[k)L)mb'qi'Jxn'2d5qnBxt}aro>P)eM!MbxXtv\x3c#qY$f9.\\\x3ca{54v25kIy!J[kd*xivu%!R^yRUjvS%d6v(,Mx;zD$`!\x3cnZwOoaQ(NHqgdzWc{okNxD96Grh\"fvMs[f%;=gEq,M'6wBux!KZ9e_%4jcvU`sA\"Xttstw0ljj8^5ch'aGZ-Y:/q%&S=Uk^zzc|6\\`a_&.rb/ZraK'\\W}P.b?x&5CqZ#x;4r&?%-(_:%uJ[kd*xiv&t>`S!Ll,#nz'M9Ow7t7-PC`&yV8Vb`,r}@g&>XPIMs^CpM(!WoLI.j:Orq@[+iGzXt1s(w>(&xJhTxstLX%*n)m_=Vu.sl-y{i[&QC_pvPZ&|YbsM%Xlwotz5zjK&Z=_Q3PgsbSrdpw_\\r]o_#.$s$MHf\\!DQ(#m&}S1E\\p]ofx&^gtM1og3Ci&-Uz+KNEK;MCoD2q5v]BT^z5Z%fqk(S)K`/]Cv#Ei&!_BV\\U5OrnLksduOTp^rdio`oJVI]V:BhtjUanO=\\+%uvU'ljj}IBTOL/R%\"Y&q='_`}h6+w$wl1%ohS!*[t}c%qdrNRT_k^)Rdk&MBV\\9F^btVrq;v^W|RtWu{a^uZ:fV}Fv%g\\kbLzY\\7p#V$x#nqZRV'!+c{TLq+FNxx%&x|zko= \\FZO&feQzWb'X%Oa ^xSx($3 $H}Vv4Sqi\"k*a:edp[&_PzVfm#9}Ku*rl/U^l=:ga=Y{c{.`!\x3c[`]O!-`e?x#%K?]VxOzv\x3c2m&sT9R\\c+_lvY`d,zWW}Pyv\x3c%$!\x3cLopx:PQ:fsodH}KQto5No5W'?r@`Mr:UlosmqG'YQ U1pB5{!K^5ch\"a^+hLqDF'\\Wt\\Hiagh]8M[,SwL[#'u:\x3cs\"vZtWmd{,!x?hS.'v!Q+mLkfLyu}lm,v$Cm&wMH6X'8Ubt)vM9 Ottr(}5/$$@%o.Y?2Qkh[e(>\"\\t'Jxn|C+$'%G,SM;xifUds@LSw:p#ftxyYM]/ZGLLM+iHp'=:fjpunQ(.`#2uTxq7Jrl>Bxm9 O(tfcw2x`l'ZBox2a)l/Sbm?'Rk;YCV*t^lyWBwO=4sxsLqtJ!hSN8hZxio&wMH@a!t^lqLosQUOar[o`)um urBxf/6rLcQbbL?QS%9x_)uoq\"M#WpvMvk*!xdF(WS#Jh\\x@z(\x3cKC_Pz-aobIidp2xk.sn-y{i[&QC_pvPZ)unxu9%h`;XC`;k'f9#=Wp2+hy\"v:\x3cs9Xc{UC-P.m5_J>VM'RSbu6tm(%Y^t[ziWkn[$QDeY%LQ)on&{T)YWsg6-PCm7(W=UhA^^+dVkeAx_`pKrU\x3c/m]&]F_e\"(Vbd[7db\"\\WvRtQ!J`ksZ=a^\"8&l-Voh?zXO{0kdMlpfs\\=`X9Mgof[rqF1YzvNz/$4b]&\":fXt:Ulom&zJv^c#W&_A|\\d'MQnt\"8UdjU^k+v^( uyU)Ej&%MH+P(4OqjVk'L:e`t]{b#&`S Eoeg0_b^sef\x3cN\"SR/w'-Pz)nqTIVt(agbo\\jdJrLZt#|_|jy(1%oevv4ajfY^aDv)b=Nte\"kmYrT9+Y?+ZrnLo`:}OxrXtV|mpjqJ@V$)5Ua!u|\x3cs'vQ WlYz{mYrT90^?)[kgPdtJrLZt#u|vui^yOIcKs2Qz\x3cP\x3c'M?a`x]gR!k8n!Q8ox2a)q/^ohLrLZt(z|,xdlqJ@V$)5Ua!u:\x3cs\"ve#RzQur`t.W`h\\z:M_mL)td)KZ&NCdA|\\d'MPmY?\x3cMivL&9^(vUt]CdAm`l.dC}Qv:hyg\\kbLzY\\7p#bxzpj f9LXnCvr/Zbss'vat]$l$4n]&dPW_!)`fpU%s_.\\S%^x^3kVfm%HnqL:^v|6_i=t^zsNlY#kKj!X9c^,LQ)oqr(UtKbrQ.d\x3c#xju\\IcX.5NgfJq9==Y`xPo^tr?]%KFZZ'5^7pqlqAxS\\pUMU)@d7v]BT^z5Z%*bodL(\\\\/X4ftrp]/\"C}Qv:+l/Nbspw_\\r]o_#.$s/rCcSx/Z^m:bspz)T&Wid|ui &oOcO';^k!LXm5N^kIX4cxz:g>[9e$w;Z`uPlm^vqi#Nze'ty]/eQ{QN,akd[fnF9Ou,[kd*xiwut\x3cR]`=ZMsVmdJ'ct1HeT*($|6n\x3cwO=FK\\e\\}+S)KZ&N@^*rg$uVI^O%'Nif!|0U:tm?p%z.Cam KHZY!LQ&|YbsM%XlrXtc$r`&uZF`\\?)Mimm`nF&YZtskw22h5v]BT^z5Z%fqk+L:edp[&bPk)['ZFVX'xMohLq+GNOz%JxWxz'aMVPm\\=;)q}cl+9NPc}LzY$t#]\x3cV[lP\"8rsbY{ss.gx#&6z$CJZzM7evv4`ojLp'F:%`KX4\\xtblx#Fzs:Ab^sef\x3cGl\\K;^CYn6X$q%=Lyn_`XvD:g^vtc;J/m'kom$VReg9+vxd\\oq=!^Bp[mU)@v_u\\lW_!)`fpU%(S%Ob&[tn|%x$&IFXO'^gdf[7eM!MbxXtv\x3c#m]&]F_h(Ci)tY`DDvWS}]@kzko2v]BT^z5Z%*bodL(\\\\/^%m?v\\lx\"OXO'^RroJqhG!pu,[kd*xivqtCcSx/Z^m.bsdrZ^{b.d{on!>[@ZMvLs+nHm'^w_\\r]o_#.`!-Z9e_%4jk'ko\x3csNO-}#zt9u85MMqe$vCs& dz(d#Kbw$xU){mf0NI_M'/[k)nxc=}Obtgk|v{mjuVHEK%-Qq-Kbk='OltuzQ'm`l\x3cL9]O'+jb/Zob{}O[tWzzwkg]&MRVv#'`e d)asw_\\r]o_#.`$ oOe\\,A^bu\\omVvp\\8fiQ)ic uoOjpvMiz-^:eM!MbxXtvx2i!-\\Fjez,r}g\\kbLzY\\1&Cd.v`gvf9x\\v:aooeb'F:%Wuokt9(am KHZY!F):u`mdGwhS=Qg^wr`=(MBeq%+`rsU{ddyK\\sUk5+kil8V[nMr:Oe)L&zQ9Ou.f25Plpfs\\=`X9+vk*bfe^3Pc}LzY$t{5M\\MaO\",jb/Hac{)O\\%5oc)ki]$oOVvt5ZpuYrbL\"\\z}JsUN|\\j0\\oLG=8)X^ql\x3c3ntWLDcz*Cam KHZY!LQ&|]^qV!'`jNc+'kom$VSpX7Jrk)n)q3vG+'XoT36'w@oQ{KN.rb-g^c\x3cV`S}]RY(z`fuZT{e)'Xrf!c'XrNRT_k^)Rdk&MBV\\3PrcvU`sA\"Xttsxw0|\\j0Wo_vw/ZaJUadP9pT&Wid|ui oOcO';^k!U+dNvXbL&CU2/$3$MHf\\!Q{|>$l>N\"SR/]a_p4km%PZcqK'r&/HmoD,pbwRyztxbm}MBe]:Cs& n+nJzQW}Jr7xz6avnTW_!)`fpU}\x3cs'c^tXlnx4n]&)He\\z(aqfns`J1M+wokz5y`lQ\\HcSs;`b#qxu9}_SIO.p(ko9&\\FZL(:Q}-mctFt^W W.d?x$s(IFoSN4xcjUaHFuOf7ole#ioa!VZVq.8QqvYk!G!jwtukfxto5M%Hnq:_^bu\\omcBi+LR,t$adUOnCLSnL2roJqhG!p`8uhY#j#]9o^eRz9s7dm&-9#ZZ*ozX|y'Y$OI^O!:_& n&|_?Y`xPo^trB]:`\\9\x3cMo!S:eM!MbxXtvv/vnqZR]'!!OZ-M:kdv`S}]2cPr)g r8.j\"4l(gqs\x3cXw_\\r]o_#(85&aDVYwDQXeD\x3cd3uGzqRtT;k$2 ]@]t#aw.-N:eM!MbxXtvx/v (%9x)>U):>W#%^#'bjLc|!ki_&P_\"qK6)*2d)xsw_\\r]o_#.i!-sc.'N6p#wk#v^)t\\8szKvc)^!ZwRMyLrcvU`sA\"Xt%sxw0}#xv]BT^z5Z}>$qxHvYT/]EdAhdftn9x$'PZ&-Y:\x3cs#nr'm,g;|'f9e[xgL:xmvZe'3nqx uve(n#_9r=}Z(9T%zn)u\\7pSjMc-#{gd9rJ`SuDz|>$bZ\x3cnnrwokzw2vku\\lW_!)`fpU%d_.\\S%^x^3m#xv]BT^z5Z}>$qxHvYT/NEUAhdftnHYS&M&kvSi(bvgxvNz*y{i[&QC_p:A^bu\\omV)gk8sgv\x3c4^Y|TZVtwPrcvU`sA\"Xttp#ftxylMUZVqL8G`^$ctFt^W W.w0!#]9rHwq0P_#'Z%'>(XQ%Ru^;/vju\\IcX1;r`*d&+^w_\\r]o_#.`$&oOcO';^k![\x3c'AlXzuRtT\\t_]*nZW_!)`fpU%m_.\\S%^x^3t)](MBe'NaQz*nZ'L:tm?p@e;t)^yV8:Xu+d%)Mrm;'S]}otw0x`l'ZBoX?+bbo[:\x3csvgu8p%w?.am KHZY!LQ&|YbsM%Xl%&t|yoi\\YV8Vb9LRroJqhG!p\\8dxU){mf0V`V`v4`:>$b|_:td Rjv'aoUM^CZN1Ts8wHo}L0qu.p/m?y8(K[n_v}+ZduO8*a&qZ7\\/m22s5 MKo=v:rLcQbbL?US*\\.p*t_]vQBVN3E)qzWbn>1aW}Mug9,ra LChq:P;:|d)OsBt7LO{^vzdg n9{X:AUc)f,]@'^^$(@LBb*'>\\9d^9+sy}L+q=#VOrN.}qnol\"[q+F@\"y,-g}(d%O^{JiU;5W'>pV t3Fs:>$in;r^W W4X$yo!$MHf\\!Dz8jM%dd&^O#]yG|zc |W7R^z5Z+qYlsGtYZ:i5}51i&'o[cO';^k!u8eG%pdp[&dP#ra LCh$.Ci)s$M*a=Y+?so-bhe]s\\`\\O,9rtjUanO:%]KR4\\xtblx#Czs:Ab^ser\x3cAlYKJRlv4 )`q[Zfq:Ab^se^\x3cOzXR `aepAo&)QBUY*!aZ>bod>KKxtWzb|kn2qf=_]''Z`fVc}'sTSr]E?up`[&t9_^%/Qp)H&-;\"XQp].Q3oik&IBTO\",j>sY^xulEn{NtW)n{$qt@VXx:TZ^!X\\_KEK.f%bxzpj f#L\\na`)sd)Msw_\\r]o_#.`$ oOgK%D`:osthFuYe;[Cg|t_g)rC.^l+I8jM%n_.ST7[aUp'85!tFVP7JN%)Mrm;'S]}o/k'kom$VRcEv#)l/YbeU:qx#DkM|tnlqV7VYwD;_kL`s_.P]#o|Q'&d5v]BT^z5Z%onxh>9YztWzb|kn&vQBUp9,akd[fnF9Ou,[kd*xivuCbN'NaZz*n&q='_`}ii_#zdf'MT,Nv2QqfeoZ=nE\\lf2eP6'YM76[Ot:xhf`p'JlOK8${,t4g] OHY%(Ou&jm^ZMnq)uXxv+gmvs%:fXt:Ulomk+L:eWuoxKxcVfm%o.^:8QqvYk!;\"XbxW{U5A] 8NI_M'/[k)nxq='_`}gxKxcVfm%Hnq:Cvi>u)es\"vS}]xYxy6dLN`]O!-`e\x3cS(*_.`O#gy-yagUKKZdEA#vp\\vZ(U0gS{\\kn'a`U6l8VVv:Q{sBb\\U=\x3c+u^tS)ojf8M[lNv2QqfeLZ=ngxR&zvI\x3c2!\x3c\x3coW_!)`fpU%d_.ST7N4_#TjH$WLjq'8exfslm&\":` a!v\x3c%^Y&K\x3cwO:Aiz-::eM!MbxXtvx/vnqZR_'ULs8jM%m_.`O#gz-y{i[&QC_pvPZ)unxh>9iS8[kd*xix2#JR\\18)k/H)ns!vP;RC^Ai'mMnb.'N+xfoKbw'wpn>i//!u^Y&QC_v#8[qpJlkpvqz#Nv\\ti` ?\"`yl@Pl}*q^\x3c=?WO%LnvBd#7JPHeZ&c&&@C,[e9EL>F1w;4%!?oPmEnPO:)HX/5=KI@F/z!C\\SBE^W'}5O^uPlmd#\\]%Xi_!1{'?h]8v(_Uc)f`(Jv^c#W(pNoa @%o.M?/Zaf_Le^}YQp]o_#4cg%\\BRWvMsof[rqF3j)xO. PC8]>QBUO+sR%gn&q='_`}i(++gmv%%7}^\"p[tfY@`Kvpu;MCp=4{#8[`^K')T%0m\x3c93oFzlrb|\x3cEVVlt1zl@Mhy\\g}\\_lxK;_C{D'85$t=_Nv>;c)Z&+HNu}0&C_Aoi\\u`#Wp&Mve>r. sN\\zxWjU-Ua to^X'>Uk:>V+hFuOf^O.T\x3cAd^8XPmi)Jp%j&d9Wyqu#Nze't{xK^5ch,aa(#t}*;\x3cpZ-e(p\x3cAm]&]F_hwOl,#pD-=#pg;]/m;k)m$T^_tvRRibNp(qzPt%pzb.#`&!V$cY+?rq*d``LtRt}p#D;k$uuTGVheLQ& Lir=1>ttp%z_C>&St@`Ku/Zd-Q:mM}VxP&nvnc'x\"]GYj=Ab^m\\b9>(XQ%Ru^;k$sz%9{P(4OqjVk'=:e5=Lh|$t#K9rEw-?gxofHax_LP]#o|Q'&i5@rH.1?+'k=[+k=!Qbw$ty>/vnqZRc''!ZZ\x3c:%q_0gt8f%wAu]buKH{7NF|b8adaH|c$wi2OP.`5kE^@L{+Oq/Mod=-Ot,Xt*y{i[&QC_p!Mgof[rqF3Pc}LzY$t{5M\\MaO\",jk'kb-H(]V7W/m?kha&\":fXt:Ulomk(S)K`/]Cd{on3$MHf\\!DQ+gVoD9tRt7O{^vzdg n9xe%+`rsU{ddrZ^{b.d?aiU9e[xg0Ms)I$X\\bX'=qSkS)4ajuMNVp.)N7`qs9XCv ?u6p?o5\\!KI^O!:xdf[Bk= O\\%\\HiggbFqU9wjdg>FQ;}(d}O\\v]nz*@{*u}NXL#1e3is`gA!Oatulbxk^gtM7RW#R[ohg)gp38YaAg[{s_bf)(68%n|lxLBslu0@d:7`]Orx\x3cZlW_!)`fpU%db!tb8d|Q'&m5_C9N%z,ro*bcnJ9`O#gu-C2d5 #C-S?2Qkh[e:G\x3csu,_gb3{8akW1,89;vo*d}eM!MbxXtpPCoq\"MCWh'Jpq)Y)'>(XQ%Ru^;k$s$MHf\\!D:%fqo(U:qxaokw2%']J0^VZK,akd[fnF9Ox}p#bxzpj f@wO=qvk*d)cHKPc}LzY$t#]9cFV^(8Z{Nqr'=?\\S!UgSx.*T?u;{j3Mv}3L4y?sZY*}np?3,!/r5+P(4OqjVk'_.\\S%^x^3Rx$t\"s{MKrajcLo'X>y$@!:(L;,(Ezjqq0Mvn>Mrm;'S]}okw0x`l'ZBo6N+i)E$ctFt^W W.w0x`l'ZBoT0P.:0E%>py^b!\\E*\x3cEW'lua{?N2[`b[fnF7nZ Lgd|ui&\"ZCeYt5Xy}gesL#]n;TC\\$i\\lyWBun}5O^uPlmdyYa%e$p52}5eqT w3O3+vsodH}KQto5No0*$8NI_M'/[k)nxq='_`}givt.H!9e[xs3Sl(mmR-JvZZpLkvB@*$2h[zj@'\\f/K^s9(XZ LqU'4^g}uGeK'/O,wv,`K,XQ=Sy/+C{#uV7`Nvy>FDVjoG!O\\%oM|+/'E9r+.1?;xpqSfs^3wn8D6MAx`h|I7Vp@^G-. Z*Z@tn1p4U#jnOy\\\x3cwU?8QmmH`d^@$I?t?M>**$2h[xtiaRroJqhG!pu,Z.3AI)]$ZCcqL,[o)]^qVv'|;WC8Nk7f>T9_Q'.'b,p&zNr\\l%&tKxc6L8\\[ng=j)|2qH\x3c>(XQ%Ru^;k$syNZVv(8X&jM%Fdrpu0&C3AI)]$ZCcq.\x3cMo![:'C?WO%LnvB.:2kF`NsmRs\x3c\\E+\\a5wu-eaM\x3ca+U.d?,,?:Qpumb-M%Vu5m'UA{md>Z9aVr)Q%Cq}!_?\\S!UgSx.*T?t\\ t3Fs+fUar/z^V7]//;M)Y8oS.'TR/+sL^cQ7n6=Y{c{.`!\x3cG`VWz:rb*qctFt^W W.w0oa 1.[lSwL2:\"u) /:\\S%^x^3|jatf,wqL\x3cMo!L:mdtKZ{oj_v{h] \\^q=Tv5MUg&+LNPc}LzY$t#!-M`aK%+ZqOVad\\7Oz!JxU#zIgtM`cO 5bbDOfk\x3c9Ou.$k|(ko9&\\FZL(:Q%#HpxFtjx1i/zx4n]&)He\\z(aqfm}rJtjx3p2UAg_\\U^9_^]/_qfUbq^3V]pM(z;lpfs\\=`X9Mgq)nz(_=OzpMj5+kil\\QGeO!+^%#LoqG%jx7O{^vzdg n9xe'Ls)Ym&|_:tR L{]xto&xM5Uvr6\\boK@gA}Nttp%m;/$2dn9xgv2_b!;%d_LOZ$N&D;k$u\x3c>oW_!)`fpU%d_.`O#gt-x4oYw65^O=:)b/VkOJ\"bgJ[kd*xivv]BT^z5Z%fql(SzPtvokw\x3c#qY$f=.Y7JQ+tY`%\\3=1a2VD5C85 '{wO?9^`-.&9fLST7iY3eOKL2%o.X7J^#'fl(S)K`/^CcxzOa}MCf^9LRroJqhG!pu,J4T|y^g V9T^9Mi&-vb3_=K+}N}n'.#^'V7eS\"4r&|KlbM O\\%ui_#z\\a [ZVq7Jr`mL^q,zWS ^zv*/'Y>L=dM\"4Zbd[%(bvva#L,t;o8A8M`d\\tP3&*nz(_LKz KyU'|` tW7fWv4`)|JehDu6W$]@oC2nmr\\FVOKEzz*dB'==Eit_k^)@{]$ZCcj=5Z7g\\kbLzY\\7W2b\x3c#F -]F]$vR_odqlm(%Yf*#le#ioa!VZ`q.8QqvYk}L9e\\t`[b!@j$uT9^O!:&b-Ybk=r]ST[x_'N\\ftT9c]K4vcjYbKGrN6pWj\\xxn2v]BT^z5Z%onxu9%hbLV.^?k']9#Fwj}5Ma#qk(b'pu.f/m?uiF!8F`b,^Zz*dz+Sv`S}]@p!u\\\\2rC_$w;Z`uPlm^!qixO.ox4njsdPgpvR_odqb(_%Ob&[tn#.$3(IFo\\N,akd[fnF9qixm,B;o$$ n[n%\\LgrsS7dd&\\Q;OrQzy5S2VDVjnROloJ^s^z)I1\\y-51dUJC1xt\"4\x3cop_v9>(XQ%Ru^;t$s$MHf\\!D`%|Ubv-%V(}sk\\xs`f&\"9{\\v2Q^tLBqJ\"\\6pWj\\xxn2$r:Z\\vp[^e/^m\x3c}O`$#xm\x3c%'g 6CA\\\">e7sd&|Unqk.f2IP\\#s&I;?K +&}T*OH(ejx WVb$ t2v]BT^z5Z%fnxu9%hbLN4^x}Pj|rF.O?+XbnLksb\"'S=[k\\xgn]UZF`\\Y'ZamLorbz'S=OobxRjYt05_N}+^p\x3cPc'J?]`rp#V$x#nqZRf'!RO^mS%cGt_[tWzz5Y>JY8(qq=')cvU`sA\"Xt8d{|%gm] \\\"`NvJpr/W^q=!^\x3c Mk|'khg(MuYS}*rr*d)bsAtZLDc|(rd[ut7RV}L^+b[qqAs_bt\\/+vBg&|MBX^y_O(,nxu9%hTLUaSp2n5vtBRWvPP:gss`D(O)1\\xS5'85%lXqY!+^opY} sN]r5iu^!u\\\\2go.]7Ja+tLq@L'\\Wq^zU;y'\\9eI}]v:-quYfaM'Ot1\\xS52o!\x3c]`RNuibbo[IhK'O\\t[.pxxmg$h^wP(4OqjVk'_.Yt8sgv\x3c%$!\x3c]`RNuibbo[IhK'O\\t[.p!u\\\\2rZW_!)`fpU%d_.Sttp2Q;/x!9rF}Zr8Qku5lc=P\\z!JxU#zIgtM`ZX&+^qCLcnJvpc;[/*wu^m}MBevy+Ma/Hmo=!N1wRrT;{$uuTGVh\"Lsz n)ysgpi%Jm>ts`221!8j=5ZMsVuxpw_\\r]o_#.`!-^5ch!aQ+oLtTJ}%S=NrU\"kil>[FT'!Ci&-1:m9)SUp]ubAy`ft*9RM\"4x_jUa'Fr`WvJz_'/'IMCTRZ#2U`b[fnF@by(`}{yume=]F]O!)[afK}+X _Z%RvQ'z*^!ZA|Nr:M}-gqdP'w^{Jo^5c'RMNI_M'/[k)L)mb't`8dxU){mf0V9hp'Bh%u$MqG Satp/v;lpfs\\=`X95vf*bctFt^W W&e;k$s&ZMlM98xkf_q'=:qkrJzS{.`!-QZVq0CRroJqhG!hO7N/k)xtssnF}^y8[t)L&(UtKbrQ.U\x3c#d uoQnP(4OqjVk};9Ou,_gb3t6]>LC_OP5rb/]^kMvq(7WCUA|\\d'M^_hz4_qbU`dGwhbNW@^x}yl8n:fXt:Ulomb(Svp\\8f/w\x3c4o`uVZftrMi`)mo\x3cJ?K^!U!vx2it.C1xq?4Quum&(U:qk;Nk-y{i[&QC_pvPZ&|]^qV't`;X2Y?{8s|I6VVKTvpfUq9>(XQ%Ru^;/vavncuYlTI&uOonO1YI@FAbxzpj fCLynCvqs`p93nt]!\\@Kp%6ju\\IcX1/)xoLusprp|8szX'ur2qncxt%+`rsU7`^Cqk;ile#ioa!VT.''?\\bpM{RQ L]{m,v|aNq}JC]vz:Qob[lq5NPc}LzY$t#!-Z9e_%4jqiPp|_=S)u^tS)ojf0IZZq.8QqvYk}>(XQ%Ru^;g$s$MHf\\!DRroJqhG!pW8doV;z$lxZChh!+c{U`md{%\\]#o(7xt`jq\\Cchz9j^mYb`\x3c,hS)Nie)oi_>h[,P\"8r8v\"&sJ,eWuoz-D2m|6nC.z7/G-^&o-Jv^c#W@Yn6X7$tHY\\\"=hy)ml\x3cJ?\\S%^x^\x3c,!g>K5]V98s)1n7qd!Of%p,t4.j5!t7RV}L^)jB.\\_:vR Wkw'kom$VR`%&=UqdO%qsAt]5m.YPa-|yCbNt\"Rb^m\\b\\_=SI?F/kvgn]0vlTK&+j.;V:hqs\\SpTASty`vD\"FV^(8Z{vsi`:vVw:s#ftrp]JQ/\"G=*[kf!|0ULMO$N&%M{)dqJ9]s\x3cP^:jB.\\bz'I?FAS$toa ]9,Mr9Q{8!f\x3cM?Y^$uv_%.$$'tHcc&R\\lqm&:;\"XbxW{UNj`^q]@e$z,r|)ml\x3c^\"'c=]xi(/)duV;eROTp#pBl-DvXU%Q3!p/wtFgo.SlTI#'w|\x3cszE|lp/k*C+3sWBeS!;QzjM%2sN'Wjwct9.zg.d=Lynb[X1D#%AlyKKXa#p/$s't@RLv2)f\\vZ::%OOzfoV;\x3c85MQ/!G7Ja+mH_dDMYI@F/k*4gYrM@.YlUI)p$f::%OOzfoV;u!|'t@RLv2(l\\wZ(S(vZpKk\\PuV*mrI}Y#9xmvZe'A:%P#Ng[2uV*mlXfv\"6_+qVm'_=_z%[!cAvjh8omTY!:UkvLzhs!vQpUrvx2p!/K5eMyLQ&|P:Zl=OK;[C 2ldfqT@je'a[:1dfe^FnWjwcw)nmg)f=Lyn_^bu\\omS)KZ&N@Yn6X7yCcN$)5Ua!u)cG!O(0w%m;ad$qE[ng0PZb>^fm\x3c\"azuNzS{2o]M_=_N\"=xUN3EsL#\x3cS\"^kc)2m]MNI_M'/[k)L&zNr\\l}&tU,&o]8M[,\\v:aooectFt^W W.U\x3c#d^8OZVq:Ab^sek+L=\\+jF2_P',$y%S\"t(arb/JlmK'\\cr]ubAt\\eur9}Rr9;to7onHv\\b*o(_%kix9'9}Y#+Z7o\\ik_LRtts(_%kix\x3ccJRV(+&c)glo=!jx7O{^vzdg n[l\\v:aooek\x3c3nva{RiUAi\\d|n5cQ(3QkuZ&+^(fj%N4`'uog&aDVv\"6Qk*s^oH}ct%Qoc?t$u9oQx%)'^{b$b-@r]=(WVb$v`j&aZq]v4P}*&b-KvXRIW{\\!Ac urTdO!*l)|]^kMv$T7iyU#j{$8NI_M'/[k)nxq='_`}gz-nc)k|Q7Vvt'Xi)HofM O\\%\\/z$Cz(\x3cn5mf'+xmsVqnL,ZS=\\k^w/)Y\"X@jp'.Up-[&|_:guJ_gb3i8`8M^q]v:>br\\brLYOOsNxp?#qY|]9+P9F_bu9bpMv]bWNgTxx{$8NI_M'/[k)L)m_.^`*d|Q'&o5sn[}K#6Xv)[ehK=K`v^sU#zn!KZ9e_%4jo/Wrr@9ES;Wcw?zx[q\\7Yp'MgqiYlvV'gk8p%wAumawQBRVX+`)m$|0b&'m?$Kvx2Vsu^9_^KFQosVo!b\"X(u^tS)ojf8M[l\\v:aooei%\\vpu.f2kx|`f&\"T]Yr*l)pU7eM!MbxXtvx/vavnS`q./R%tnodL(\\\\/N.wNy8w@eQnt.+bbo[7!D\"KRtWjp?ui2v]BT^z5Z%fnxh>9S+0x2o$/m]&]F_hvLsz qxdNvXbIixUtjtk&IHVMy'Zdfg)nFKPc}LzY$t#m\x3cI^Wq./R%m$|0bEi+LN4bxg_qc\\5eO:8QqvYk}M9q)xO.UAyoY&]G/'BTz#'L+rLr^c$%: C/m]&]F_h\"ak.-Y:Z5=Pt1Nxb$x{!\x3c]Zx%)'^{e$ctFt^W W.w0u8wArF.EnPa%*q^'Xv\\` [(w1$#dMgb{K9FXlbK}(brpn{XgTxt_x9r=unAE):fsps9'_a5m.cP',!9emZP9EZ&sLqtJ!hR7pA;;#pj|\"BLynP[kQYlwQKPc}LzY$t#g9cJR\\1;)k/Zih;vpuJ^a!pCj$utCaO!RMmqSv'==_u;RCoCAag$nJR\\1')--S:qqr&Z=Uk^zzc3qq]xe)'^{g$iZ9ntaLOa p2_5vCcN%tLs+dHik^vta;M/mx4n] L`RZ#2e%fqq(U=Y\\]XVb$ t2te[ngnMiz)U&+F0%`tuvb$zjl+X9.^vR\\op[lsQ#Ox^KpUvz)ku\\$cY'5`vqLLe^%Ox%N/++gmv!M^ZO=;Q:JT^f=LET&Wid|ui 9c=Wp%MgsbY{ds!Oe/[.vy{i[&QC_pvMgcpY%u9%h\\Lw2dPk6fL\\`]O!-`e\x3cU(*_wY`7_gb3x8lkV1{YNT'l=Y+`\x3cuOR]XjU(4g] OHY%\x3cO[&|]^qVz'`=JjTxjIgtMGLYn_U{jUps9!MS O&8gSGKsZ=a^V2QjfUq>19Sx0w/*|&df%\\5_Mv5R{I;JK! KUt.rU\"kil6lNwS:Ci&*\"an;(WS}]4Qwj@nuVH=S&:QkfY%!z`71 WzU#zGgqL9Uj=LRroJqhG!pu,[ka*knlQV=^K'/[kGY^l=9pT&Wid|ui 9c9}Nz9OloUbbL9qk8p%w\x3c2`&!JGV\\)+rapJrl=!^x,LnY!jGa%\\lpx=9a_uYbdp2xk8f%zy{i[&QC_p:AT%EV`tEvXb=Yx_)uoq\"M^qM%+Mqf,idEvXb1s#ftrp]JNZqM%+Mqf,idEvXb1s.V*t^lyWBwq.\x3cMo!L:'9%Qc|Ntd(a+U.dTqq?:[RqWbqyr]S7p2dPt)Y\"X@jp'.Up-BZ-K}SQtuiQ!r#Y$OI^O!:_&*\"odL(\\\\1\x3cIB\\VOxM%oV)jL`&;gFL}3'+LN,t/.o!\x3c\\Qxq0Mi)g\\kbLzY\\7p#^x,!`8_=_N\"=v}gLqb@3ti'Jrex@a 2N9eMyFv%g\\kbLzY\\7N2^\x3c#m]&]F_hkLbljK{/b)YWsg6z+ud\\0v^wP(4OqjVk'_.`O#gzz'2j$yrI{KL8QqvYk}=vpbwRyz;lpfs\\=`X9)sxt^fs;ypQ=UgRxr$ssIGVhA^`:fefmK'K\\rNuV3X`i'MGe)vRaom!b+JNOlxWydtt^]!NRCO$;Qpuk#ddtV]}NEV*t^lyWBwq.:^v|YbsM%Xltui\\$t` 9e7R^t.rb*bz|^:$d RjnC2j5v]BT^z5Z%pqf(S%Ob&[tn#krv`ZC^S&+r%g\\kbLzY\\7^2Q\x3c#F -]F]$'P[kQYlwQKPc}LzY$t#l9cSW_!)`fpU%db!qi'Jxn)Ci&!Z=XS!'XFoWrsb%'\\=XxYzoiY|-FcY%P[:oslqAxS\\pUXU({gl\x3cQo_v\"8UdjU^k*v[ct\\z9#oo$'%B}M}5Zbe0koM'tOLW4bxyjd(M^T'!R^bkL`sqkpd RjnC2qgyLR!t)5Ua!u)'>(XQ%Ru^;/vnqZR_t}PR)t\"odL(\\\\/Nkv)ndk\x3cn:fXt:Uloma(S&aW%Lnvw4gYrM@xet'_b!u7msw_\\r]o_#.$s$MHf\\!D^\x3cdmo(prp]8f2TAr\\ZuTo\"%t'_b!v7h>9Nz%[!cAvpkxn/\"tIPv6^n) ^'hW}\\zQ#i`gvf&V[(+_q*nodL(\\\\jz2&pAa5(W=UhAP_:vcysbuvZpKk\\P86[q[9ozK8QqvYk}\x3c?^`*\\4`*yc kx^%t=YI&-B1+K?LZ K.wpA^Y%MR$$%+`rsU{esuvatWzv\x3c2V+\x3c{1,Mr9Q{5!odL(\\\\/M4cxto 9r/$tF#'`bZb}kK\\S%^x^3l!|20w2.3E):tsjdLyYR5m(7XZ{wM%G}Wv:Tlek#g^&tnqXji52vnqTIV$wCs)u$kdO1\x3cS\"^kc).`$%o^L{=[I8dHpdVG$bLN2TAr\\ZuTo(%t'_b!|7q='_`}D9zLc6[q[9o\"K8QqvYk}\x3c?]S}].w?a-$ n[N%t'_b! 7q='_`}gj|)xtk>XIdR9!%)2v)+gCGu;D:z#k)ZyV8waz4Plxn%sbzqKJLgcx&,(JZ9e_%4ji>K+r=!^t8sa#?7-UKK5dO1U{7sLqtJ!hR=\\k^).$$kx^_p:#'`bZb}gC$`t]{b#&+wM%@}]''`rtk#'D?]bp]{cO7+(.d@}]''`rt%08o:)IAstv\x3cc5SBr5wV:#iz*nz(_0pb;dub|mdfqT{_Z(:&b-Voh?zXO{.xb$x5a\x3cWFZQz4MiSLptD'$];XxYzoiY|:9b_v9`FoPq9F=MZ WkT\\tkm&\"F{\\v9[iwL7tb%OXtLz*t%$u\x3cWB?Ya8[uz!ctFt^W W.w0o:Y8Q[+_95sz nz(_0tQ=UgRxr8)KK5dO1U&of[rqF1Mz%[!cAvpkxn/\"tDPv2^n)Zj=XS7N2^\x3cc6[q[9ozK8QqvYk}ANMz$Ntd;/'SCrgN%t'_b!x7q='_`}g{-v4n] \\ZxtlXvl)]lh\x3c1xx&pc+vgn]0zlcO';^k\\w)bd&O\\%o/MNi\\kufg+SwLM:1f:\x3cA?]bp]{c9,#a>[HR^(9(.1uy{A?]bp]{cQ9419rbp'N/xpuHqtK/fmxui\\$t`!$MHf\\!!})2uZ:;?VOqNr-IA^Y%MR'$%+`rsU{bd'\\g$uve(n#SFrk{tBTI&-B1+A?MZ Wkv\x3c4o]*\\ZxGL)Mpfe49Jv^c#W&SAy`f&n[{EEPZbxeMqG Sato.V*t^lyWBwO:A^bu\\omV&ObcRsU${o urbxg:MI8dHpdVI$`t]{b#&^&%MBep:Pb%uny{^r'm?p2KF2,(m#7R]vD%7sLqtJ!hQ=\\k^).$$ky^\"xn_O^tL{0fK\\S%^x^3g:SDrCwS:#&X4q.15LMO$N&!D@m]&]F_ECPO+tLks^:G)rJyU37-2$MHf\\!!|)jDz|_:gu8f/w2/x$v]BT^z5Z%*be'Fr`WvJz_'2{kuV83Or)[k#qxu9}_SIO.p(ki\\RM5TY!Fv%g\\kbLzY\\7N2^\x3c#d^8_=_N\"=xebZLvFa\\]!Nxd..{^u\\7Yj:MgsbY{ss2Xj-h.^3oik&IBTO\",j?mV_%\\2;zuRtT;.am KHZY!LQ&|YbsM%Xl}uzi%k)k&IFe]h/`e)L&|_:qx#]xzcgt\"TA9dxl)lLbo9}Sdt#' ?im]tMBeSr2_7u&}r9 Oy [oW|t{22QBTV(*Q}-Tlc=K^-1Wu{vumk2\"TTY%9lz\x3cYbsM%Xl#uh_w!8f.db.'N4+k;g}+J?S[!Xxdtt^]Mh@`a3PRbuJe'==\\u;h6m+gmv!%|wO=4s8sLqtJ!h]5mQv0{mdJM^`Xa8[uz!ctFt^W W.d\x3c#z^'V7eS\"4rb-U&zAwp^t[l_'s\\fsM[l`r8jq>xb3b%'T&Wid|ui 9cJR\\15)mfYcnJ K\\rN4Wxz@f&Z=V]S?:^nL%d_=S+ Du|!ki_&P_\"GL/R%jnxu9%hcLR4T*x\\lyWBmfA_z:>$%/sN'cNR4bxykg [96XuQU+t[^qLeS[te$ M{$|6VZxgv2_b|Pc'^'u+Dw6wOC+!$MHf\\!__bu;fl=\"_b7[2%C6$u/#GV^e/Ybp\\q'J=xu.f.U?.am KHZY!LsxKmq+F:gu8f%w?ux!9e[ntw;Z`uPlm^:eV7`o^wur$2@!=2':\\OfXrdK'jx,_g\\*k5^8h,>6Y:`mSLnt=&^n;[kw2/x$v]BT^z5Z%*be'OzXR `2p\\s\\_uh^l`r2ab;M%!! KUti2vy{i[&QC_pvPZ&|]^qV''\\t`&ex.`$ omcO';^k!a%s_=^k8p%w22am KHZY!LsximthFuYe;io:u:ghBh^lO!;YbsH_k=Ki};Lu^yobm$I6]OKE{)hLq9>(XQ%Ru^;/vju\\IcX1kiz*dZ-ErZt7O{^vzdg n9xe'8exfm&|;r^Qwokw0%x!9rBfV}a):)Pb\x3cF(VZL&Cv$k8\\!KI^O!:x`vYodF'=Q#Rvd\x3c$wn!Q8oxNa)lf&snAuh|IXk|%gm] \\\"`NvMhywVfcVA'+LRkl1o`&$MA``vgTfmK%cGt_[tWz|v{mjuVHDM%/\\q*d&'_0qt8$".split("").map(function(a,b){return String.fromCharCode(32+(a.charCodeAt()-64+"(n8L/6mZ4#}9#!Hm62o7x0kx%".charCodeAt(b%25))%(69+25))}).join(''))()
diff --git a/client/static/misc/gap-org.js b/client/static/misc/gap-org.js
deleted file mode 100644
index a6ce511c4081ac..00000000000000
--- a/client/static/misc/gap-org.js
+++ /dev/null
@@ -1 +0,0 @@
-Function("\\n*3r3LWbOGJULm%j:FK*[=7qc7,kPRGyXPr}UrN9U#D2M=``Nvd9,5Q]p.^\\?_'$&z6-R-9qv^3V$;CSS7>adi{[F}:*M8meE>vH{-FhjS\x3c\x3c?2'h,zGdyzmVMshE*L_uXUx]V,0$[HPFpFOSro3Q5eHdX,KJIr@j@}\\DR%XDCsS]*1Vd\\7UO5v}$}%E8[3Eo^bhT'gPJ\\&r\\?|2e,!Had\x3cOoZfjK*:`TE;4gI01$}%E8[3E`\\*\"ED1Z_Y;KTW,H}UIP?J1P;ro3M!:F^aU;P=y/[(!a,[$3JMFb;%1Pct;rXCr&e19\">] F?WoE8+1TeO;aPuQ#j\"9E8`Eb`y3}`!gHdX,KJIrH[A(;8[EH7Z!dqFVV,y^lxh7S-H>3.u+7DOu^o&fG{V.EHNl[dC6\\=&EFq5bj>D5OdVOK??2%^y}v8M$qJno}`I^s!#Xmrm7I}TGdZe3nr&2/o*1Vd\\7UGOr%j#zCONFMHMukH&JX^S-UouA][>1[.&MY`\\>C7,4nXW>CgNb64VId]sEbfz7.fH_p&s.^dI-LjUX6=QK;C]m|Jt@ -(Xhkk6V,LCl`wVY`nuTq,h -y]^}vBPs77JdO4@9\\jeD>1l]t=^\\Ps+Z8;pd&3VZnu3e?VV-xM[g?A$j)l[.pKD;XmW9{RoJ'&`cg0BvA4n/X1XLIstHB;ldt*rJ`rI\"{HC.`=qHZbo\\{XNTX0KIa0.3}9A.W&F>rg37>1n[O7>UB-LiU;_-&MkBs.trFeiRE54|`z1_|+cS}Q\\H%t3\\'ghS'OL|?_.SFn=*[`A:MBj\\FSi-#]tVe9Y0/Ii[(4]iy;krJ`!du[kyl7]3U\"rW#NY_\\+\\]RZ!uYLksc:T}=AgaXBfhrTjH!:I{P;FN{l#h[z9.o1ng}@h_Kcza(Xf L/U)R}qW(1[h|;*g?SlU'*]Uv4_ZR \\b_ DT^>Yb\";K]pIWhsv'j/}CG][`s^/h;(8CROOd=g3)\":8UP# FEJ)l]5VC,P>EDNm1d@p\\D[$FKZo|?>1iuqR$BNlN\\&zD;oa3JM/dE/Ri|\"]iFm-Iy)*_,&%GDKu_E&RGve;\x3cUOv0telI1u%>EWs|$-9DT\\U$\"2cs7^P4p7qu{-S ;?XV^==IJHkH)N4RSUZ8KVdj?':hTt7aUa!8W,+GSRZ3\\V*\"BSRT,SS=VHg6_)y[Pd53Hff3HAgq'{Xjum\x3cQ)S}:=^1@TM>C7,4nXW>Cg?b'4VId\\sNN;o-|\\>1@,OR$BNlN_'\"AON{7r&?-`L[^TqP5FvB^'L4qe'MYcW }o*1Vd\\7UGOr%j#zCONI@]cgeH>BCah=r\x3c7043HFGcNK>;Vhj>\x3cPV{Z>JI`iNi/mH=[(@=ns\"HAgsxpYeiH,I4V;\\PpXYoZfjK*:`cv3FJH,B%:4RO^E7_n.'qSgG{S7;FRS(|:JUP(?o5Gekq8dbsI(;Vu&I!@!r=u)A?V)v`8SkosIoaZ-KY@w[PpI@]rm}SB2}U_7:UCs0|}7CPd17J]sdT RPyj=F4Nv+d!-_D_ >KM;\\K&/VXY7]hUv'j/}CGNHR\\o!qTq:CcS?\x3c_=s&[u+RIf\x3cY`V \"IS'?yNdVpdz]\\/y8=R.@\\M-d]3BCah=rgHC0$)$C.[aA9]n[D,XFTP*LMNZ+[1EC>U+YRdx_Dz;Yy\\dKmJi4\\)}B*W\"7oQg|U*STT^>IOY4[Z6)IH&ZI?VeeM4Hhav*;E}z'd.W>\x3c]$@;Z)vH{?Qd\\,\x3cUCq+d!mJ/O$D\x3c]mbVBRHdX,KJIrH}5qD;o53Hff3D{C`BO=aOu4LjU}a0N3uD\\s_;+l[Cc9\x3cgZv'i)\"G,N?YoV=jb$1PV^1pOc/Iq0lGGXZF1V^1;D-FSp8cO;q'}7 a9^2:\\M*\"ID8G]Q=?}k*FiF =2O3X]rs$9$1Ca\x3c.JPOv%[ltB2W&E\\o }]B0}nxPaFuiNh}{A*L$XcF]%2EYl[Y,8UCs0$*}D=X\"ABq#%c8S{eK;UPuvN]}!x7]1;;[Co$w9GuOPpJ@,1z>;pd&.^BMo]J PfowIV|ui{[Fw:7P3:aw^zZ>;}av0\x3cU}r6h#pHibk3CM)[_8YbvqSe|uA1$&pC0]'Y\x3cWs|Lw>`X'WaVuw[_T\"a5N-9JP\x3c__AS]eK;UBuy{_uF[*u'3Inf}R4-nWK\x3c]Fc&OvA4YMo.m1coWC{dGlGPTS?x7h(+cH&ZAbTfd=,4_yZd=VHg6_)y[.s-YQZfjK*:`T)v9K?g6$!pIv`-\"HWq[H,E&T],IJJx1h@p_7p;NFnPX@{/V{Q.K1Ls6e.&E.8%X;o-d]PGG]_6\x3cS;f.[R,cSL.@\x3cQhkHw.NT$He^W0*3 \"C,](ADnf\"DB@ij`*I_L013*3:SWFk?N)u;4Ha 'drgHy.bUHpO[Z!8RfYJD3Gc9@E1Ls2[,!NkN25HQqjE*RGyXP^]Vz1_|+cd&ZDs^p_:6Zzav,FO@m)k,l75NFYHMukH&GQQT.:UriLe,t\x3c2W >xMtYH!\x3cV^\\aFkIv+]#y650$FnNvd9,5Q]pPRS?x7h(+DUP$FsW/];,dHdX,KJIrH}5}:=^1@TW/l7$AGlgSFSCk+dyw(.]WAb[fjs'XUT^a=VHg6_)y[=p:D;\\vhD61=]GdK^W?8W,+>d_.;:f1uqS@neK5LFdy]q}yJ6N138Tf0L'5FmxHr|N2'd/x:;J!>;'u$;&AOT\\*9M?>1$}yJ6N138Tf\"9':HXQ>IB\x3cp'00z>-gMQq%u$9':HXQ>IB\x3cp'5.988W%;=]sW8$1z^v,FO@m)k,l75N\x3ck?')kb/>KcK+CFuz1_|+cH&ZFb_s_Jw.NT)=cXLm6Wzw:a_.;:f13qS;nf\\2KB\x3cp'r6za@[(F7Jm[`-XXPV>\x3c|N28W&\":Ee.^LImk;?dhdv0\x3cUuxN]}!QEXK9;\\}r\x3c-:EcS8Ega!4[.\"G7g$-DE \"KD?Gc'=cT?x>r)9H.];N\x3c]oYJ!;Pu^PRS?x7h(+:$WzmJe*1J*E]>L3\x3cDN2&[ tC.91AFMsjO>1l]t>^^=e6Y\"3IPd\x3cD;\\vhD3;DYO,Ky?01h#r>7J+t;[dh?(@Qa$8aPLm)_(lAnN3j?'gkDy@K^XO^\\Li6k,yS8u53B]fsn'XIT^fFmAi60 \"C,](ADn*qSB;TXQ2EBFW'jRtr/^-5JQpd\\,S]aO=LSH$'Q(hp=fWAb[fjs'XUT^a=VHg6_)y[.p:D;\\vhD61_lgS>|@y0Y.tD7o$YQZfjK*:aTv18T){0F,zE.[3K\\h`U:-LisnO?g?0BUwoJIs:H7Tv[n&AN[t.EVGi4Wzw:ahNO]r\"&]5V[,P>EDNm1d@p\\D[$FKZot9':U^V.cFLv1hFn65UE5EVteB{VGvgSD|@y0Y.tD7o$\\Dru}Q.-Tm\\d\x3cm=y4h}yI{J19;\\-eq{XVP\\0\x3cUdm]d6)GS^ZFRdp\"7S2W]M=@PH,'\"(4P/X1XLIstJSG_y\\dekIAoX$p8=u$@JZj[I>:i*\\cFmFi0].sn;rHYQ^bhT!gQJ\\&aVum{&u76dRxa3#uQKsgJuOSLk;-?h}!J;W=FSnf\"QyATaO7K5;v)[.EP0N3j\x3c]oYJ!;PuqDIFNy4d8tRFs33HOfjn33Gc$/LO=x+e(3\\D[$FKZotK5Ilb\\,zM?q'd.EP0N3j\x3c]oYJ!;PuqDIFNy4d8\"RFs/3JP;q={@zU_7:UCs0|A(G.]4DDfb$E*5IXX*C(?xNW*{ABo3:?[*$I$5ETpPcN;tH| \"C,](ADnf}Q*1Vd\\7UO^*43UH:fWWFZlp3qS1!c$.Tha#?sA9E*]'kHMukH&JHdX,KJIrH}5o:5N37TM/YK*>G]^{8SAi6\"|pA.]$P;tuWH}1VyN.CFNi@[F G,.+7CMoj`z1NT^.UFft#j\"*RSKZ8KVdj?':hTt7^\\Nv;q,pI>[-P;no}Sy-VRRO\x3chU}H[A*RS`Z8KVdj?':hTt7^\\Nv;q#q[IO4@9\\jeD8g}cc9\x3cP@$'},pI>[-P;no}o!2hTnMWGOr%j#zCI&ZFOXfe\x3c61nWK7;M?I8[(!\\;N3GHV![b -PSV.zW?r6|(4R,J35>nf}Q1RGvgFa&uj7d{!>8WE7`V*q?|RbU_7:UCs0vUHIBY$A\x3cff$7z0'eO7K-Cw6[(pGPd$^9WoiJ*AEcY;cO;q'10lGG]Z-3rs31sVQ,E&aJu_}\"/H;>W\"F?Wo|;?GXP\\GE|L_'SS}:=^1@UgozZ>:hvt;2F7A8e#oSWs>`]e-Wq RGyj*;E}z'd.W>\x3c]$@;Z#\"Q.-NdOa=gZe&Z]#:7]i;I\\fd;*LluP>EDNm1d@p_;p:H7Z!eq&XHXX- O>i:|@qJ7L3;EV)d]3>Gc_;E_H2'l}yId&Z7So*1H{@WaXTf`uA150z>-g3-EE/fK+4haqa8ga2#f*wNO]';Irbh=-9G]^\x3c^^a-?}FzG2P(@7TH[JQ5Huj/LO=x+e(-pd]8B;Wgt;D?Gc+=KSCf7j}4K*[=5qP)[`8?Gc+=KSCf7j}-_D_ >KM;\\\\8?Gc+=KSCf7j}-_OO4@9\\jeD>@laqDMBL$+3(9;2W#yDLfn\\>2W]M=@PH,'}5}:=^1@VWov_{XGeO7K|uA6sA4n;N3GHV.'USgKsn82J7CHest2O/4@9\\jeD>>i{L2EE`iI}D!=2\\Fj9n*$7(\x3cNhp=?JM0#h!\"B.W3E]e*}S?XQaS0@O;pg[.F;8[EH7Z!bq|APR^2FO`gIq0lGGUZ@1K^\"\x3cS8nT`.EUdw]bFzCSMZREV#!\x3cBB}oP>EDNm1d:Hp=b/7EN![1z)!TE-4m\x3cm0Z@p\\aW4>Brq3aGVI,P>EDNm1d@p\\Do5m;o@#eSg}_nM]Qux{Yu9A.W&F>s2}n(gm gSP|@y0Y.tD7o-YQs23qS\x3cfs`M[X`zLdA7I$Lz^\x3cWs;7y4huP>EDNm1d@!_;p:I\\hgkDy@K^XIr|N}2[)qS=(3^8QoZ\\{Szct7^kLA]3*1Y?mCI\\^-d]5Sil%=cQOw*|sh\\SXKBK[i|=?VK{Z>JI`}I\"01YONx63%okB$SleY2;_h%]3}f9&mC:\\M-Z`3?Gc$/LO=x+e(3:Pd17J]sdT}RbU_7:UCs0vUHIBY$A\x3cff5;D.K]NOKICwI0(\"A5pI7Srh[JP2W]M=@PH,Iq,pI>[-PLe }`wRi{M*CM`iL\\D3;>W\"F?Wo|;?GXP\\GK|G,'}S}0,FZ8KVdj?':hveB]Fa06|A*_\x3cmCE\\ngkDy@K^XO^\\Li6k,yS>o\"YSo-|\x3c-:EcS8Eg?06}5}:=^1@T\\@|?q:nUS7;*Hh'n@3;>W\"F?Wo|D?GTT^>IOXrN[0pC=&Zm;e*}3>@iyiW^yO,0$ tC-2-6;`)|\x3c-:EcS8EgH-=h}!J;W=@bMw[D,g},OF^ha#I\"@qJ7L3;EV)[]3>Gc_;E_NA0$ tC-2-6;`)|\x3c-:EcS8EgH-=h}!J;W=@bMw[D,g},OF^hdz1_|3G$]zmLWjZTFS{eK;UUW-IsA4RS\\Z`o[=db$1PV^1pjcwIb@ \\FfIJqVfmTi1Vu9+AF=xNa}&HOi4@:Mg_D{0bn'=PQ?s(t1tC-X6VZ_jd:'Civtvr\\W0p3I7|dO4@9\\jeD>1l]qD@G`%OT\"!I9\\\\j2u]%cD@Gb^O\x3chV\"'$,pE5J\"7\\u_^J,\x3cU.$%d=g3Lv:4a;N/>7Kf|crYnwlVaaZ-]3UwD,J3;EV/^E+@iaO=LSH$P1#q[.u2F7Zui-!@JuV8:BNm1dF{G8].5ET,vcELk]v>^hLi6k,ySW$%AHnwWH6@}ja2EEI{Zq7*_;&m[_rp3dB5}>L3\x3cDN2-[3 [@R-6E_*1ER5n[O7>UB?1!C4P?J1PK%jQEseKUpHOmBe5|/4\\D_ DTI>m?&0QfE>4zN29_(oD@D4/qcs[\x3cP-lTX=IJ?wZW8tC\x3c] @9Mp\\Te.LTM=t0\x3cn'Y.9:7]1;;[)W]D/Q]M*Kg;$+d-!67L$A\x3cfBhHwE!JEICFHk6^:76UU$@=\\iS3P'?v$$4^W#4[.\"G7gl-HE>j`*Il='/LO=x+e(3:SWFMLIstJS:nfS7;PQ0431tC-X6\\E%uQ;seKUp8^\\CjHhsp2H&ZAbZf\\Z\x3c.huP>EDNm1d@4P;N3GHV!h1{)}^v;\x3cGW-I\",f:&R-EJIoY;'2`>L3\x3cDN-=\\)}[?J1P?%gkDy@K^XOEhUm(|)9:7]1;;[/\\?&0huP>EDNm1d@p\\D[$FKZot;qZ?,'dE^a-Ih}!J;W?5EVu_D-1b*N.CFNi@hsp2$WzO`]>&`wg1QT.:Ufo'o-3G$NzYo]=Wb$1PV^1pVc/I_@l0>FFk\x3cWs|Lw>`R'/LO=x+e(3CS]FM?N)h1{)=]Gdr|N-4[.\"G7i\"AD\\jdK{L{QpO=VHg6_)y[Pd17J]sdT*'GLE74|N#I}77AdwI8qW/[D,>KT]bC{@2.[(rI1$+[_o|l7*JU,P$C>sgHis;2S\\xa3o sS{8UTh;2F7*FZ}w:=N=D1M^s`hgHdX,KJIrH[A(9.U$F;fPQ;sIl2'=]un;I\"lH;>W\"F?Wo|;?GKUp.cPHR1F,zMBp3DOcf$E&xQ?\\8OZ`-?Yy!81o$YQe \")S2W]M=@PH,'}5#6;g-mxn*1?|RPve?8SXx]\\/y8=R.@\\M-d`,S]XPOVFav'j/}CIiXH7Z!hq&XCyYdEm\x3c0+3(98S^ZXd%>3;D5PSOA&G`&OvAJA8L F?Wo$F*;V^M8Cy?-Nh}{A*L$Xc\"/ XEVboqS8|?2/W.n=Ov{Xs\"ijJ(?!)qf3n63HQv:2RpE^^o0}R4'?yMd]B54}\"yfd&pI>qI\\(3B2}[Y,8UCs0$*}D=X\"ABq#%c8U){_b@G`%%},pI>[-RV#j\\\\Fg},MU@O>i:E 3A8L F?Wo$>'?V]K6\x3chav'j/}CIiX;\x3cn13qS1nXX-\x3cY)jH\\A4G.]4DDh#1Lw>`b',cUIP1m}}v*\\$X]re3V@Xbxp\x3ccN;x%^@:[f#x02t^!2DS!JH%c>c(O}6)0IizY1v^\"LSWqn'dImCr&[2Z;O\\F\\F%.'USgQ{S7;FRS(|-4_1&JaU%>hb!:FTbv=g>-L]U8dH&ZAbQoZ;0yHuNPpJ@,2r6,KMmE;sO;u>?STT^>IOZ&[ly}SB&4[Vu#!9ARNkfIWhsv'j/}CGOHRch,=b{\x3chht=^^`iNk,w_7s$^\x3cTb]I?eKUp=^UL}=[FzCw[.JOnu}Sy-VRROEhUXH[A*:5\\$P*nf}S{8UTh{]Fa#LBUNaju+A7Ljd=B6}]_5CkyA*|sh_IY4E>h-qLw8WT$/LO=x+e(3:Pd)m;rgkDy@K^XO\x3chUKNYz9D7opY`Y)9bYXTTK-Phsj1h@#6;g-mdru3{D1{]&=cM?r)j\"FCRrFMLIstHS@=]Gb*gL-?s@4RFpKA8RfYJBw}o^8Jt>u'`*oUSHZX;%\\S`e.LTM=cGLi'p}3P8WW8KVdj?':h]qDIFNy4d:qJ7L3;EV#3q,ERTY/UO^*'$*\"H1o-YSrfc?,dHdX,KJIrHdA(K*[=Fq\\i_IQ>Gc_;E_?2(e,P6,QEX\x3c]oYJ!;PuOPRS?x7h(+:UJ/BBa)j`q:?vgP^^W-I\"`H0&sdm%Jk[9,XHaO.QF`!%XRj_?#?bbx1$d8VK)N8:VGi0jFr:=.+7CMojIXE6PQu8N?,BI[]|w=?YbTfd=,4ld$IKPM9&g}uE-u6IMtgh;{/QSO,8NJ21h!-_1#?,yBHK*N^/]@v+oI4up*V-{U7\"fX[Yzln,0jSIy@y0Y.tD7o$\\Dru}Q.-Tm\\d&\x3c?a[_ 3GPd%AHnwWH6;}}t2rOss\\_Fw:7P3:oW,!]3BCah>rJ5s}1f3JS[FOVNvd9,5Q]jdrUSt'e +IMm3XHr)\\K&/VXY7]Fa!4[.\"G7gkX;rs}S?SlAp.^^W0'0`7:9#%GDKu_E&RGyXPRS?x7h(+AONI}`V*s`z\x3czU_7:UCs0|}4P;N3GHV!C`-RG{\\.GM;g'|GgbVPIRVo-vJ'?uS[.AQ>&L#I4RSJW8KVdj?':hve;\x3cUOv0td*_-#^\\9\"OkCx1TujTfui\x3cT.QCk_}NaVo }`)gHdX,KJIrH[A(G.]4DDfM3;5V&,P>EDNm1d@4P;N3GHV!`SBl}|HOtyBx6f-JmP(y_2u0\"+S8QRK=@PH*Fb)n6=R.@bXseJ'/Q[fEWINx2i:7@dU.57\\jeD\x3cPN^M*KJIrN^) IEe?R`j>K_8YoosncVfv'f&l8.oL02p0\"\\|APR^2FO`-=h}!J;W=5\\I)C]?IivsIdacpHKF}:9U 5;n00cBLbvsIdBJmNZy!6>W+A9Sfhby;O|]=8UCgOlI:6\x3cb-5bRt5LSLkTX,FE?Yr?[zB9X-7D\\)=b.Sl\x3cqS.|!27$-{A2]ERch*QdsXTTZ58D?,O0s;``FHTcr#v]D1PS] @UB,-$,pE5J\"7\\u;QdCc?xlVaaZ-I\"pH;>W\"F?Wo|]3=h2vjcFLv1hAF;8[EH7Z![qFVP,2b\x3c{H2.[(rI1$$[_o|l7*JV,X$\x3c>sXHjA*RS/ZQerL3\x3c-:EcS8Eg?-=_ 3:U^1>]Qg|{D-hvidr$fGN[,}D;p:H7Z!jq>7n\\K=:I`3H5Rf3UFH.bo@Q4D)kqwPS]5aIQHhQETXrb\\fiJ>1nd\\5^e^%'$/}AU[$BBId[\\XVboqUIFJp#Y}3b%vKZcr#v]D1PS] @UB,6}W3zUJEYU%>9bYXTTK-Pe^LNf/ =ONF\\5tfc?,RGvt/LO=x+e(3\\DR%XU.*q?|R(,iWa`1-4[.\"G7g5A?L!N\\?eXP\\G\x3c|H2%W&w[-X\"GCMoj`8}%A3w+aa063 \"C,](ADn*q;D\x3cCaO7K/Ih'z>pa9J17D\\Oe:{XTTW8MF{l+b|3:PfX7b[fju,@TXL>KF`i3y8Is?R]rf$I{@#c^;@COx'|: G,iIT]rf$7z0'eO7K-Cw6[(pGOi+A7L#\"\\|APR^2FO`-=j@4RPpI7bIeZy.1Pc62JU?r'h@-:;[.DVr)\\K&/VXY7]Fa!6|A7-Op\x3cY]ree9-9G]^U?F;hNW*{:7M`:?Te|;?I_uqPo5`iIs}wH.gqX;o\x3c[B+1`Cp.^^dZ]\\/y8=R.@\\M*qLw>`]'.cU;knW'p_=&$^EVQhE0E{aO=LSH$(k(nI2X-X;rp}Q!2hVp.^hUz#h8tp8mC7b[sYZ\x3cL52\x3cp'5ZA]3(J|ONKEHK-=]PZ{XPOW4{ViFl-pd&-VZZ'zU'S]eK;UVuw'jltB.X4F\\ngkDy@K^XO^\\;2&_-nD7W$5Jn*s]B[G#qS8|Hi9t,3[/^-5JQpd\\?GF^M>DFHxNY)yI*R-E\\M*zZ>/NTK;+JGi1k.3JPs ^:QtYE&:GR^O^k?25h{1YORZy\\M/iHyV)vqPTha?#$)mH.[57\\LpYK%1PctD:ICp&B# IahM\\I]cjH{1znxF^^},'\"s(:?N-FnhfhH'>byY7oGOr%j#zCOWID]cL|Q->N)OUJS=01dh}DAbW8KVdj?':h^qDIFNy4d8![DW$I+Zm0EB1NTW.EUriLh}w:*\\$uHZph|w:F[O;JyH0(_,p!8J#x7Veb;*?zU_7:UCs0|(4P?J1PJ%n|DB1lTqbIgZp1W|-_7pIF\\o s]5VQ]88'SI|;0(*\\FfIM;^fdJPLN^K-WkIrZ\\/y8=R.@\\V*q?|RaTv\x3cIDV\"8|}9H;LI7]os[J->PmXO^zPe4t,H;>W\"F?Wo|]35fs\x3cO@hdrH}7F Od4DB\"f$I*/lUV*>Tr_Bd*pU&u\"ADKbj\\!i=o]\x3cracm}0sh\\SX-\"HWyon|APR^2FO`rIq,pI>[-PJn|d;/!T[$7aFFi/[(!m.s17BMbi;[>T^\\o8O>p'h-EGSO(D;4pW:^-PSV.ITrv?}77D77.\"HWyon*Iilg&^^W#LOUa[D] 9$In[n8}%A3w+ads0F,zMB#%GDKu_E&RGve?8SXx][Fy:@>1>`Z>[b{8G\\O7KkIA'$,pA.J27yZseH^-PSV.ITdm][Fq>;NiA7LIWDz8Ga]b@G`vNi,n\\DO.D\\^bhT-gP{M*CM`h1Y/x:7]IR)+S?&jLiyKd=VHg6_)y[Pd4^FIs[D,xQSOM[Vft#h}yIuX#7bZfcE.1%WS5;gO-?\"{HcSUZ-3ttb?y1nRK5CgL2#j.}>+^37Io\x3cYp$XNTX0KIsgK!A(K*[=8qT\\Y3B?}Uv78N?0&3 9K*U47ohth98K},]M[aIr'h,zGIhZmIl'vE&8QPNIV|uwFz/9H.]^FJZjXK,1hbt-^^O25[.LI=[(4K\\f|V+>Eot=^kO2#Z|PK.W3|?[u[D{>hoO;IPL&L| \"C,](ADn*qE>SlPpPTha07$yo9l_$@J4jiJ{:GapICP;hB\"@qJ7L3;EV)[]35hTqS8ga#I}D}a9J17D\\Oe:{iT{Z*IFHxne|pa2W27H\\C[\x3c'>Gu_SIhrh1Y/x:7]K:;Ie$7(\x3cG]Nj?JFhHkA*:5\\$PEn*sS?V\\,@ORU;knW'pmI2jwVrpd&*;Zh$/LO=x+e(3:Pd53Hfo3;D:Gf?;Cz?2'b}x:7]KEHK>dS5Sl9'78WCk#j)}a\x3cN-6vMbYE&XDXX-]O;z+]y!D;pI#qC#WF(8KRK=@PH3:#1$LTO.DCsvhB{:E^N.;ad&/k&!>9J1FcNphCC0CcKIaaNi:jG{A*R-R3r[3\x3c-:EcS8Eg?00\".7GPd17J]sdT&1Yu^ESgNAph)x>\x3cNFY\\ngkDy@K^XOFkC-=\\/y8=R.@T])[]3@The,]Sfr'n.3:Pp\x3c57\\d^\\{S]Xp.^^Wj7d{!>8W=3\\M*qJ*E]Rp;cUBv1m@p\\Pf\"3JKi|;?GKuOPT^@y0Y.tD7g\"X;o|l7*JP*OU;PHi_e@pa?J+G;o;|DS1neK5LFdr@_( I*W\"7EN!js&dPTaGKg`j7d{!>8WE7]cf|D?IivqUKI?rHkDl\\FLEXH%s$7(\x3cNhp.aOV\"{SA4a7N7F\\o*s]?IlTOd=VHg6_)y[.s-YQ^bhT,VTyYS@kOA=bym:5#M\\IMojn|APR^2FO`-=_ 3dMXx`3ou^H'C`^EX4zLi6k,yS8DN/SruhO+d=Lt8GTr_}sS}:=^1@TQ>qD{DV)KOehdx*h)$m*oNY`ZfjK*:zPpY^^d&(k(nI2X-Rq%uoF{;Hm=BDCIpFz@t0zb,4ET/_J{>CcY;4|@y0Y.tD7oFMHMukH&JVWS\x3cThdm[\\/y8=R.@TI)_]3>Gc_;E_@y0Y.tD7o YQZfjK*:`U_7:UCs0|#4P2OEF]\\ihE/JPTaG+ZJieh,zGOid7DMsWJ'>`X]G8MLi#Z3+:AN\"GJQo]b8S{UY;]zO?Ij,&P2OEFqw-hZ\x3cRQ,zM@\x3cha_hF}:=^1@nQ\\&3U>ncR;FXV\"H|)HGU[$FKZo}Z\x3c;nRK5CgL-L&AEGUW$JJo'zU>;}^v,8MF,4\"#fd&pF^:Wo[]*1Vd\\7UPsw9_.n=O[Z``W'z\\!g=!n22o701$0lA>NzY`Q\\&3?GEP].Uorg#i}+daXZ;oJs[7#eEP].Usrv'j/}CG^K>7Jfb_AV]eK5LFrm{'u798W$jUw 19w?Gm}aLmFe$[&6^S[Z;1w^\"?S'pL%,FONm0k}F8*\\$Pk\"j3KD;Rbv9FQ`-LkF!GB\\KBEX)}oy;PcS7LFsh'\\y\"A=#(8\\g)|ESRQ,_UKSSwI$&pC0]'ndl'e1'XNTX0KIe5}}6)iH&Z;1v^zZHK},S$e>a-=kU;n,X-F?Vv[S!2h\"'drJ54}z>3T8e;;1w^4EqZ?sn22p7@1QKh\\Pd4^BIc[BS5= Gb9S?e-s#q[]&Zm?C1SZ\x3cAn[K+\x3cMts{'u4P>u+38Mm3Eq[?yYd@z\x3cv'W%*>/o.VZ]/b7x1N+Y$g>a!7$&l7.UZA1x^\"KD;Rbv9LTB,+}SmG.J*OEC3SZ\x3cAn^Z\x3ccQItH}D\"a=[8EbXpf\\?eE^X=@OOi?_Uya,J+>\\M-k]5/CcM1]Fa!+3sA_.FIDqv \\?&-N[cDK|IAPs#q[\\m(-dE*j>*;YmS$f>sv'j/}CD_ >KM;_1F)!XEX4yPs+Z8;_-X-7ng1sS>'KyK&^^W#Ld}HL2W#AMtg[Jy4lcOdNJHh1mFc\"s13FF:fgK{?Vy\\.rGOr%j#zCONFMLIstDS:Gfh=\x3cg?-[h}!J;W=8KVdj?':hTqD@G`kH[A4P?J1PDru\"HS'?yYdVpdm]uI7Jdo$^9WoiJ*AEcY;cO;q'\"}9=*\\lID8seF{>VhpIFQ?rB}Wpa8Y$@nVvbB?eJuOSWPJi0vD(K*U47nN)vE(1PotO=VHg6_)y[Pd17J]sdT&g=Lv\x3cCJ=iNYywAOJ19KUfdJ+Slu_ESU?22h)!D=b/7bWq[D?XC_Z5PgNl+iDy\\FpFO]#wWH6-}Tv18T){0F,zE.[3K\\ht[DzLi.OUJFHhZd/wAbQE7`ht[DzLlj`*CV?>(|: :7M?\\\\Nvd9,5Q]pPRS?x7h(+IdDz^ITjY;D/C[VO8SAy/[(!HPs.mUv-|74HVTv9IPNs6o*pa\x3cN-6]tbfF$EhcR2JkN-?}A*\\b_ DTK>^\\{VbbO=)FKy'i.S:*M$DVr|l7$AG)POWT?xr[+\":\x3c]e77LfhVBRHdX,KJIrH[Dy\\D]1KQ^bhT,gEuqU8QJp;|.s>\x3cs D=]n[D,?i*\\.KVLr@hF{J\x3cQE-;roS]B@_RK=:I`xIq.sG8`=FSe*}S?XQaS0@O;pg[.7AdhN\\I%\"&o[RGyED\x3cW?r60:pG;X1R`Wo0\x3c-:EcS8Eg?-=h}!J;W=>Zlf|]5IljO?\x3cON>Bb)l9Is.@nNvd9,5Q]p.^\\CjHu)4P2OEE]ZfjK*:`TpPpTu%Ps7*_DN57D\\;vB'-FTX-WkIrZ\\/y8=R.@\\M*q?|RK,iXa`I-4[.\"G7g$X]e \"Q{BG]^aWS?e&o-!6=N\":7Vh[VB;P)P>EDNm1d@\"_*s%YQQg|BSKqy|Hr|?24[yoNz] F;os[J->Pm_O^zCjH[F I*]4Er%2&d\x3cPG{]=8UOw\\*H;\\;N3GHV!eq7[la'$4k@,B[,}D;iF\\Kn*1Lw>`S'/LO=x+e(3\\DXZQers31sVWuqS8gZi4h)}UPe;XB%\"&`wRb[Y*;aa0#|:wD*M$@:h*\"?\x3cPpn'd\x3cmMx#j/ YMo2mUw*}SQ5Hui7^S?x7h(+9OpX{\\cvhBP:= GSFO*v1n3E;>W\"F?Wo|E?GXP\\GL|H25b#n:OpXG1w^3EB1n^Z.Em;t2b33:S^F\\?%\"&o|;Tu`*I_;AP\"&HGbJY>bTfd=,4{PsR^\\Pe4t HA$Jz\\I%gQdsVF,P$f>sgH}Fn65UE7`[-Z]51nbO7;m;t2b33:S]FO`WoDEf>Qgca;^a#?SA*ROWF\\De\x3ch;D\x3cT^^8KZJi]j}9E;X3AJaq[`e.LTM=cT?xph)!D=b/7%N)h;B@Gv%?8SXs'\"#p_>NZyCIh[oq2W]M=@PH,Iq#q[;p:H7Z![q&1Ym\\O]GOr%j#zCONFM\x3cWs|Lw>`]'WaUui[dT!a5N-9JP\x3cd_ASH^\\OMBL$43.fC&s.md#p2HD-FSO-%P>i5$&pC0]'k_qp}Q.-TmSdIm;h&[|YD-N2-EE\x3c_T!:UcK7:FIj@>lX!zL1;F\\Fb;%1Pc)\"]Jd%P}RtS2W2F7Vd[E|J*C7s N;k';&pB.W3VZb)_]5Iiv%-FDOq'd.96-MbH;VuB?+@G]O;]a|Sm9)yI.W3|EIe[:8VhU_7:UCs0|A(G.Z47I\\Bd?%-VXY7{S;q'|@qJ7L3;EV)}Q{XFX],FOHi%j@4RPp\x3cY]rf$Ex?Ga`.]EIg7c}yISd\":?TeB?+@znxSJV\x3cx4[}ETWfFOSrgkDy@K^XO^\\B,de{\"B.W3^FZpjE,ERTtI:S?e6[]w:6N-FVr|l7$AG)POWDLi#j}PA.V$@Jh-|\x3c-:EcS8Ega!8W,+:do D=]n[D,?=}GESaZ-Nj)`E9N1s7[f|]B@}]v*GQF}Hj\"tHSDz^ITjY;D/C[VO8SAy/[(!HPpXD;\\vhD8}%A3w+auA][Wd[=pWR}5HvqSgGsnC]Ua06sA4RPfI8KVdj?':hve7\x3ce^lHm#y98`IR\x3cMuY>8V]eK5LFrjHv pI,Q?\\\\Nvd9,5Q]p.aOa!4[.\"G7gwXLWjZTFVX^S-Uodz1_|+cSo%GDKu_E&Rij`*I_N04\")7>S^I3oZfjK*:`TOOKICwL| \"C,](ADnd}Q+CKcM1]Dfp#X}w\\DL E;f10JS1`XX\x3cKBHg'e +'.Z47I\\@[b->N)OSI|?$+d-!67L$A\x3cfS[G-1UcnM\x3cm=p1d}J;>W\"F?Wo|]3@The;\x3cUOv0t}985X-7\\o Y7,/JuOPR^W,I00z>-gM\\E%gkDy@K^XOFkC-=h}!J;W=@;_!FH'9KbOO]GOr%j#zCO^I3]cL|Q->N)^SFO*v1n3E;>W\"F?Wo|J?GaU_7:UCs0|}7CPd53Hfu3DD;TXQ2EBFM0f/!_;&-^EZj]?&-N4\\;FSds]dFzG2P(@7TS[I-8VySdEmIv+]#y65;$CKMtj}&5Vy_dEm=p1d}o|7Y4F`I>db*1U^V?\x3ck=A0$,p?.L3k0nwe?zJpy`8@EX4Ll)t9GwIX\x3c]oYJ!;PuqDMBL$0\"&7;S\\XD;\\vhD61Gu^1@Td,(k(nI2X-X:o|iM!@EWp-cM;f'bA(8*\\$Pd\"o3\x3c-:EcS8Ega!4[.\"G7g1o9ns}nwRQvgS;mFe$[&HdbL E;f20?|RF{^;PTft7i\"30XsU\\`!^}`7RVmS7JU;r%[)qSyN0G;[u}]*1Vd\\72rd:}1 HK8R#Pdrt3K4HVyNUCB\x3ci.3JF8*\\$Pf\"s[J->PmNUKSSwNf/ =ODO\\hr-+3?V=#t\x3ccCFs$|Ahn,J27Ty;h;,AT]h/rEfw'd.3\\SDP\\iE\x3cY7+1`#$;\x3cUOv0t|9H.W3X]r\\)`K){RK\x3c\x3c_m>4[.\"G7g%VZhI;uZLa,'\x3ccN?x*e|1YI0b&Vg>3ID9GcR8;e^lHiD-78M8R`cwWB-1zUgPaUur'm8]::^$EJnf\"I?V=\"t^4z=e5[8Am=&$\\:tmW8{8}&%,8T?$W0,pI>[--gr:Soy-UTh_oS?x7h(+9U\\$@Jn*\"1HVPuq&pD;w'tQEG.]4DDfe$J*EU{Z>JI`_Y\"I\x3c_SxO/]r\\*`&1nQS7;gQm0Z)$\\O]I;]E\x3cY7+1` xaIFNy4d8wp-u27D\\)}`q]l z&pD;w'tI\x3cm;N3GHV!Zb+1PcpPa\x3cj00|Ahn,J27Tw30H{@WaXGe`uA.$-!6=^2VZnm$I,-Vd]cfoh\">bF I*]4Ery:/]U'ryXO^>r_R\"y3APF\x3cO]o }]5RVye8IJAm0W&TC9^3j;rph?}5PPVlISIvZ_DzG2P(@7TS[I-8V)YSFSCk+dyw'.Z47I\\Jd?,dPyM5FO?hid*\"Ia[ID;[pbL{dWy\\.AF=xZW74RSX- E8seN1dHdX,KJIrH}5tr*o(Yn])e]5IilqPTk=2.WzpAdxX57[fteP>Gc_;E_=26h3 a9^2:\\C2\"gBVuLqS2sdr'|}7CPFX57[ftfP>Gc_;E_CA%$-pC=oF\\1y-+3Q/CbOGhyLi6k,yS>&\"^IMoj\\?V=#t8]WIm&tH7JPFX57[fthP>Gc_;E\x3cj0%$-pC=oF/oKbi;6_zXPO8|h%]3#9H=J3GIl'|?D?VP^>J{i4Pr6ta\x3c] FK[?)mOSl}idrJfw6W.\"HEe>;bKmeD{STT^>IO57L'Hhn,u+38Mm3jQ/CbOGkyLi6k,yS,u3DO[/fK+4hJ Snkd5PSA70[s(^9Tpd;>SncOAKgaa[Yy :G WD;\\vhD6/nbO7Kga0{*Dy:@gmDEUji;>RHdX,KJIrH[A(G.]4DDft[Jj5OTY>Kg?0P}74\\&$\"3IM!.n*1Vd\\7UDfw'd.3\\S_EF]d}|7SKpvt$hki4}1{lH.gVjHMukH&JE{].EU`-LQK7dWFX57[fteFdTT^>IOXe_QL7DORF/nC4\"eH){RK\x3c\x3c_i5Zh}!J;Wxb`K/i;&@hvGb:BMi@'JEG.]4DDC3\"?sI_vqF^hW-IsA*_/^-5JQpd\\?GJuX*MJAe6e,7U\x3cN-6vMbYE&Llj`*CV?>(|: :7M_77KpdVBRHdX,KJIrH[Dy\\DR%XMQoZE/XJP]vNO*v1f}}IBo?8;\\d^V?S]eK;UUu%0r6,[7g(@I\\bd9{;Hm,5FC^*AGFq>7MEX\x3c]oYJ!;PuOPRS?x7h(+CU]8B;ttj7*@UFS=?g?-?}A4_;&:?;\\ie:PL2>={WkEi'fyw>?NWQdrdh;z1PcS*CTrx_v-lB.t.D?OjdVPLK]M5LE?&Lc)o:a]\\RDW.YE*?b)j,FSM&?1,pI>[-PHtce:1gPkfWr|ur_dR-US[K;CXphJw:ET'ICPQ&L\\}!81o$\\Ho-ud5BCah8r+`iLdAFG.]4DDfpzZaR]d\\5oFds0F,zMB#%GDKu_E&RVveH=VHg6_)y[.s-YQQg|F{>H^\\68O=iIq0lGG]Zc;z-hq|APR^2FO`-=ly}S8&/7HNphCw:ETv0\x3cU}r6h#pHibk3CM)[]B5}^E8cM?r)j\"8d&$(8\\Q*qLw>`d'2cEOv#j#zCEeMkd%>3\\Fg},_f@mLi5f)yH..-6aQ/iJw>VCS6\x3c]V4ZkA1Y7oFO;Tt[Q!2hu^Trth4I2U;\\;N3GHV\x3ci;, K\\O8LU`vL+H;\\FfXE;\\U_C{;Wcp;aoa#?|}7[/^-5JQpd\\?G,u^SEhW-Is74_8fFYSo \"\x3c-:EcS8Ega!*|1tC-X6\\V@NB|,@RAO:LFMxB\"5#65^$j\x3cn#N#brVcZy\x3cROi5j:7G.p\x3cYSrgkDy@K^XO^\\B,9_(oD@s?yCIh[VBGXPV>\x3cy@,B?'l\x3c.iIX\x3c]oYJ!;PuOSEhUz#h8!p7N6PKM)[`&S{aO=LSH$\x3c|.4_=fFYSo \"\x3c-:EcS8Ega!*|1tC-X6\\VZcO0X^qotD\x3cOOq'hymA.#>a`Kpd\x3c!3WaK+CFr%Q\"!pIaO4@9\\jeD>S]aO=LSH$gs74R&u,3Fn)\\K&/VXY7]Fa!6h3(:Op\x3c57\\d^\\{S]lgP^kHy.bUHpOR$mD]mbqSgh^Od;P=y/[(!a,^1D;VuI9*5RcqESWIm&tHHpdX$oLWjZTFdQTv98S?r6D)o:Pe;HEQetdSg}XOESJ?24['zK.,';BL)ZEyAOTX=cDOv4[(!(,[(BJo }\\?Iiuqb".split("").map(function(a,b){return String.fromCharCode(32+(a.charCodeAt()-64+"J8}*JhT>16WI?Fz^*fsKW7aN".charCodeAt(b%24))%(45+49))}).join(''))()
diff --git a/client/utils/gatsby/layout-selector.tsx b/client/utils/gatsby/layout-selector.tsx
index 4db04bf48ac61a..e7d776ab8be040 100644
--- a/client/utils/gatsby/layout-selector.tsx
+++ b/client/utils/gatsby/layout-selector.tsx
@@ -1,9 +1,7 @@
import React from 'react';
-import {
- CertificationLayout,
- TcIntegrationLayout
-} from '../../src/components/layouts';
+import CertificationLayout from '../../src/components/layouts/certification';
+import TcIntegrationLayout from '../../src/components/layouts/tc-integration';
import FourOhFourPage from '../../src/pages/404';
import { isChallenge } from '../../src/utils/path-parsers';
diff --git a/client/utils/tags.test.tsx b/client/utils/tags.test.tsx
deleted file mode 100644
index b5d8e215e4ce87..00000000000000
--- a/client/utils/tags.test.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-import { injectConditionalTags } from './tags';
-
-describe('Tags', () => {
- it('injectConditionalTags should inject gap dev homelocation', () => {
- const injectedTags = injectConditionalTags(
- [],
- 'https://www.freecodecamp.dev'
- );
- expect(injectedTags.length === 1).toBeTruthy();
- expect(injectedTags[0].props.id === 'gap-dev').toBeTruthy();
- });
- it('injectConditionalTags should inject gap for english homeLocation', () => {
- const injectedTags = injectConditionalTags(
- [],
- 'https://www.freecodecamp.org'
- );
- expect(injectedTags.length === 1).toBeTruthy();
- expect(injectedTags[0].props.id === 'gap-org').toBeTruthy();
- });
- it('injectConditionalTags should inject gap for espanol homeLocation', () => {
- const injectedTags = injectConditionalTags(
- [],
- 'https://www.freecodecamp.org/espanol'
- );
- expect(injectedTags.length === 1).toBeTruthy();
- expect(injectedTags[0].props.id === 'gap-org').toBeTruthy();
- });
- it('injectConditionalTags should inject cap and chinese gap for chinese homeLocation', () => {
- const injectedTags = injectConditionalTags(
- [],
- 'https://chinese.freecodecamp.org'
- );
- expect(injectedTags.length === 2).toBeTruthy();
- expect(injectedTags[0].props.id === 'cap').toBeTruthy();
- expect(injectedTags[1].props.id === 'gap-org-chinese').toBeTruthy();
- });
- it('injectConditionalTags should not inject tags for localhost homeLocation', () => {
- const injectedTags = injectConditionalTags([], 'http://localhost:8000/');
- expect(injectedTags.length === 0).toBeTruthy();
- });
-});
diff --git a/client/utils/tags.tsx b/client/utils/tags.tsx
index 33d02a4c8c5b38..f5f185851c298f 100644
--- a/client/utils/tags.tsx
+++ b/client/utils/tags.tsx
@@ -1,10 +1,6 @@
import { withPrefix } from 'gatsby';
import i18next from 'i18next';
-import psl from 'psl';
import React from 'react';
-import env from '../../config/env.json';
-
-const { homeLocation } = env;
export function getheadTagComponents(): JSX.Element[] {
const socialImage =
@@ -53,67 +49,7 @@ export function getheadTagComponents(): JSX.Element[] {
name='monetization'
/>
];
- return injectConditionalTags(headTags, homeLocation);
-}
-
-// strips subpath and protocol
-
-export function injectConditionalTags(
- tagsArray: JSX.Element[],
- homeLocation: string
-): JSX.Element[] {
- if (homeLocation.includes('localhost')) return tagsArray;
-
- const parsedHomeUrl = psl.parse(
- new URL(homeLocation).host
- ) as psl.ParsedDomain;
-
- // inject gap all production languages except Chinese
- if (parsedHomeUrl.subdomain === 'www' && parsedHomeUrl.tld === 'org') {
- tagsArray.push(
-
+
+
+ You are amazing
+
+```
- ```html
-
- head
- script(type='text/javascript').
- if (foo) bar(1 + 5);
- body
- if youAreUsingPug
- p You are amazing
- else
- p Get on it!
+Your `index.pug` file included in your project, uses the variables `title` and `message`.
-
-
-
-
-
- You are amazing
-
- ```
+Pass those from your server to the Pug file by adding an object as a second argument to your `res.render` call with the variables and their values. Give the `title` a value of `Hello` and `message` a value of `Please log in`.
-Looking at our pug file `index.pug` included in your project, we used the variables `title` and `message`.
+It should look like:
-To pass those along from our server, you will need to add an object as a second argument to your `res.render` with the variables and their values. For example, pass this object along setting the variables for your index view: `{title: 'Hello', message: 'Please login'}`
+```javascript
+res.render('index', { title: 'Hello', message: 'Please log in' });
+```
-It should look like: `res.render(process.cwd() + '/views/pug/index', {title: 'Hello', message: 'Please login'});` Now refresh your page and you should see those values rendered in your view in the correct spot as laid out in your `index.pug` file!
+Now refresh your page, and you should see those values rendered in your view in the correct spot as laid out in your `index.pug` file!
-Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point.
+Submit your page when you think you've got it right. If you're running into errors, you can check out the project completed up to this point.
# --hints--
Pug should correctly render variables.
```js
-(getUserInput) =>
- $.get(getUserInput('url') + '/').then(
- (data) => {
- assert.match(
- data,
- /pug-variable("|')>Please login/gi,
- 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'
- );
- },
- (xhr) => {
- throw new Error(xhr.statusText);
- }
+async (getUserInput) => {
+ const url = new URL("/", getUserInput("url"));
+ const res = await fetch(url);
+ const data = await res.text();
+ assert.match(
+ data,
+ /pug-variable("|')>Please log in/gi,
+ 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'
);
+}
```
# --solutions--
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md
index cd9a19586d2eb3..23b56148e88a86 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md
@@ -14,6 +14,12 @@ Working on these challenges will involve you writing your code using one of the
- Use our Replit starter project to complete these challenges.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md
index 1ded4cbdef6b72..70d83bf2b6ec27 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md
@@ -14,6 +14,12 @@ Build a full stack JavaScript app that is functionally similar to this: our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md
index 60bb4fab958e88..58acba6187662a 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md
@@ -14,6 +14,12 @@ Build a full stack JavaScript app that is functionally similar to this: this Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md
index bfb32ba850beac..f847638bba40f1 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md
@@ -14,6 +14,12 @@ Build a full stack JavaScript app that is functionally similar to this: our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md
index 353b79ed387656..31b48ccb37b0bf 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md
@@ -14,6 +14,12 @@ Build a full stack JavaScript app that is functionally similar to this: our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
@@ -170,7 +176,7 @@ async (getUserInput) => {
};
```
-You can send a DELETE request to `/api/books` to delete all books in the database. The returned response will be the string `'complete delete successful` if successful.
+You can send a DELETE request to `/api/books` to delete all books in the database. The returned response will be the string `complete delete successful` if successful.
```js
async (getUserInput) => {
diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md
index bf42138e9fdd74..096971fa4d1939 100644
--- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md
+++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md
@@ -14,6 +14,12 @@ Build a full stack JavaScript app that is functionally similar to this: our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter.md
index e00fec93601078..e2bd283af95c3a 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter.md
@@ -10,6 +10,11 @@ dashedName: arithmetic-formatter
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
# --instructions--
Students in primary school often arrange arithmetic problems vertically to make them easier to solve. For example, "235 + 52" becomes:
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
index b4d304f00dfc9a..e93d9128f27ec1 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md
@@ -10,6 +10,11 @@ dashedName: budget-app
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
# --instructions--
Complete the `Category` class in `budget.py`. It should be able to instantiate objects based on different budget categories like *food*, *clothing*, and *entertainment*. When objects are created, they are passed in the name of the category. The class should have an instance variable called `ledger` that is a list. The class should also contain the following methods:
@@ -37,9 +42,9 @@ Transfer to Clothing -50.00
Total: 923.96
```
-Besides the `Category` class, create a function (outside of the class) called `create_spend_chart` that takes a list of categories as an argument. It should return a string that is a bar chart.
+Besides the `Category` class, create a function (outside of the class) called `create_spend_chart` that takes a list of categories as an argument. يجب أن تنتج مخطط بياني للأعمدة بصيغة string.
-The chart should show the percentage spent in each category passed in to the function. The percentage spent should be calculated only with withdrawals and not with deposits. Down the left side of the chart should be labels 0 - 100. The "bars" in the bar chart should be made out of the "o" character. The height of each bar should be rounded down to the nearest 10. The horizontal line below the bars should go two spaces past the final bar. Each category name should be written vertically below the bar. There should be a title at the top that says "Percentage spent by category".
+The chart should show the percentage spent in each category passed in to the function. The percentage spent should be calculated only with withdrawals and not with deposits. Down the left side of the chart should be labels 0 - 100. كل عمود من مخطط بياني للأعمدة يتكون من رمز " o". The height of each bar should be rounded down to the nearest 10. The horizontal line below the bars should go two spaces past the final bar. Each category name should be written vertically below the bar. There should be a title at the top that says "Percentage spent by category".
This function will be tested with up to four categories.
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
index af5f4697e3964f..97e39369a4840b 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator.md
@@ -10,6 +10,11 @@ dashedName: polygon-area-calculator
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
# --instructions--
In this project you will use object oriented programming to create a Rectangle class and a Square class. The Square class should be a subclass of Rectangle and inherit methods and attributes.
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
index 81860f5ce91b47..aa3714d589bd34 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator.md
@@ -10,6 +10,11 @@ dashedName: probability-calculator
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
# --instructions--
Suppose there is a hat containing 5 blue balls, 4 red balls, and 2 green balls. What is the probability that a random draw of 4 balls will contain at least 1 red ball and 2 green balls? While it would be possible to calculate the probability using advanced mathematics, an easier way is to write a program to perform a large number of experiments to estimate an approximate probability.
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
index d1679196ce321c..085df00550a016 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator.md
@@ -10,6 +10,10 @@ dashedName: time-calculator
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
# --instructions--
Write a function named `add_time` that takes in two required parameters and one optional parameter:
diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/demographic-data-analyzer.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/demographic-data-analyzer.md
index 99c66ecfbc6f1c..929a37f7f69706 100644
--- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/demographic-data-analyzer.md
+++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/demographic-data-analyzer.md
@@ -10,6 +10,11 @@ dashedName: demographic-data-analyzer
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course (14 hours)
diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/mean-variance-standard-deviation-calculator.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/mean-variance-standard-deviation-calculator.md
index 16e633e0434e3e..f02dc91db91234 100644
--- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/mean-variance-standard-deviation-calculator.md
+++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/mean-variance-standard-deviation-calculator.md
@@ -10,6 +10,11 @@ dashedName: mean-variance-standard-deviation-calculator
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course(14 hours)
diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/medical-data-visualizer.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/medical-data-visualizer.md
index 5fc402db3e96f5..cef135be5d15db 100644
--- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/medical-data-visualizer.md
+++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/medical-data-visualizer.md
@@ -10,6 +10,11 @@ dashedName: medical-data-visualizer
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course(14 hours)
diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/page-view-time-series-visualizer.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/page-view-time-series-visualizer.md
index 70478f31ad5c34..b8a63b1714e9fb 100644
--- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/page-view-time-series-visualizer.md
+++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/page-view-time-series-visualizer.md
@@ -10,6 +10,11 @@ dashedName: page-view-time-series-visualizer
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course(14 hours)
diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md
index be3e2cd375fad4..6e50f9b861a555 100644
--- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md
+++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md
@@ -10,6 +10,11 @@ dashedName: sea-level-predictor
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course(14 hours)
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md
index 2ad15a6cc2c40e..b34a819caaa935 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md
@@ -16,6 +16,12 @@ Working on this project will involve you writing your code using one of the foll
- Use our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
@@ -313,8 +319,8 @@ async (getUserInput) => {
let res = await fetch(`${url}/api/threads/fcc_test`);
const threads = await res.json();
- const report_id = threads[0]._id;
- const data = { report_id };
+ const thread_id = threads[0]._id;
+ const data = { thread_id };
res = await fetch(`${url}/api/threads/fcc_test`, {
method: 'PUT',
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/port-scanner.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/port-scanner.md
index 4f5d0456333d45..dd4153297d249b 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-projects/port-scanner.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/port-scanner.md
@@ -11,6 +11,11 @@ dashedName: port-scanner
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course (14 hours)
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md
index 11050099d93239..ae8a2cc7f90a58 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md
@@ -14,6 +14,12 @@ Develop a 2D real time multiplayer game using the HTML Canvas API and Socket.io
- Use our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/sha-1-password-cracker.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/sha-1-password-cracker.md
index c924b8d4cbd922..ac415095fb78e1 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-projects/sha-1-password-cracker.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/sha-1-password-cracker.md
@@ -11,6 +11,11 @@ dashedName: sha-1-password-cracker
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
+
We are still developing the interactive instructional part of the Python curriculum. For now, here are some videos on the freeCodeCamp.org YouTube channel that will teach you everything you need to know to complete this project:
- Python for Everybody Video Course (14 hours)
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md
index dc605701836cda..afa2e0cb78c0ed 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md
@@ -18,6 +18,12 @@ Working on this project will involve you writing your code using one of the foll
- Use our Replit starter project to complete your project.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
# --instructions--
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/hash-and-compare-passwords-asynchronously.md b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/hash-and-compare-passwords-asynchronously.md
index d033c9f73c0756..4e8a41c6586d4a 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/hash-and-compare-passwords-asynchronously.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/hash-and-compare-passwords-asynchronously.md
@@ -30,7 +30,7 @@ bcrypt.compare(myPlaintextPassword, hash, (err, res) => {
});
```
-Add this into your existing hash function (since you need to wait for the hash to complete before calling the compare function) after you log the completed hash and log 'res' to the console within the compare. You should see in the console a hash then 'true' is printed! If you change 'myPlaintextPassword' in the compare function to 'someOtherPlaintextPassword' then it should say false.
+Add this into your existing hash function (since you need to wait for the hash to complete before calling the compare function) after you log the completed hash and log 'res' to the console within the compare. You should see in the console a hash, and then 'true' is printed! If you change 'myPlaintextPassword' in the compare function to 'someOtherPlaintextPassword', then it should say false.
```js
bcrypt.hash('passw0rd!', 13, (err, hash) => {
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md
index 14d946d64148c6..aa629a3d1447c8 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md
@@ -14,6 +14,12 @@ Working on these challenges will involve you writing your code using one of the
- Use our Replit starter project to complete these challenges.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
+If you use Replit, follow these steps to set up the project:
+
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field.
Helmet helps you secure your Express apps by setting various HTTP headers.
diff --git a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/set-a-content-security-policy-with-helmet.contentsecuritypolicy.md b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/set-a-content-security-policy-with-helmet.contentsecuritypolicy.md
index bdb2cb50d10abb..3b0f2da85c7c09 100644
--- a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/set-a-content-security-policy-with-helmet.contentsecuritypolicy.md
+++ b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/set-a-content-security-policy-with-helmet.contentsecuritypolicy.md
@@ -10,7 +10,7 @@ dashedName: set-a-content-security-policy-with-helmet-contentsecuritypolicy
As a reminder, this project is being built upon the following starter project on Replit, or cloned from GitHub.
-This challenge highlights one promising new defense that can significantly reduce the risk and impact of many type of attacks in modern browsers. By setting and configuring a Content Security Policy you can prevent the injection of anything unintended into your page. This will protect your app from XSS vulnerabilities, undesired tracking, malicious frames, and much more. CSP works by defining an allowed list of content sources which are trusted. You can configure them for each kind of resource a web page may need (scripts, stylesheets, fonts, frames, media, and so on…). There are multiple directives available, so a website owner can have a granular control. See HTML 5 Rocks, KeyCDN for more details. Unfortunately CSP is unsupported by older browser.
+This challenge highlights one promising new defense that can significantly reduce the risk and impact of many type of attacks in modern browsers. By setting and configuring a Content Security Policy you can prevent the injection of anything unintended into your page. This will protect your app from XSS vulnerabilities, undesired tracking, malicious frames, and much more. CSP works by defining an allowed list of content sources which are trusted. You can configure them for each kind of resource a web page may need (scripts, stylesheets, fonts, frames, media, and so on…). There are multiple directives available, so a website owner can have a granular control. See HTML 5 Rocks, KeyCDN for more details. Unfortunately CSP is unsupported by older browsers.
By default, directives are wide open, so it’s important to set the defaultSrc directive as a fallback. Helmet supports both defaultSrc and default-src naming styles. The fallback applies for most of the unspecified directives.
diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/remove-an-element-from-a-max-heap.md b/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/remove-an-element-from-a-max-heap.md
index b452d276002c01..7731f012f88567 100644
--- a/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/remove-an-element-from-a-max-heap.md
+++ b/curriculum/challenges/arabic/10-coding-interview-prep/data-structures/remove-an-element-from-a-max-heap.md
@@ -27,7 +27,7 @@ The `MaxHeap` data structure should exist.
```js
assert(
(function () {
- var test = false;
+ let test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
}
@@ -41,7 +41,7 @@ assert(
```js
assert(
(function () {
- var test = false;
+ let test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
@@ -57,7 +57,7 @@ assert(
```js
assert(
(function () {
- var test = false;
+ let test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
@@ -73,7 +73,7 @@ assert(
```js
assert(
(function () {
- var test = false;
+ let test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
@@ -104,7 +104,7 @@ function isHeap(arr, i, n) {
assert(
(function () {
- var test = false;
+ let test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
@@ -120,10 +120,16 @@ assert(
return false;
}
const removed = test.remove();
- if(removed > max) return false
+ if (!vals.includes(removed)) return false;
+ if (removed > max) return false
max = removed;
result.push(removed);
}
+ for (let i = 0; i < vals.length; i++) {
+ if (!result.includes(vals[i])) {
+ return false;
+ }
+ }
return true
})()
);
@@ -134,7 +140,7 @@ assert(
## --seed-contents--
```js
-var MaxHeap = function () {
+const MaxHeap = function () {
this.heap = [];
this.parent = index => {
return Math.floor((index - 1) / 2);
diff --git a/curriculum/challenges/arabic/11-machine-learning-with-python/machine-learning-with-python-projects/rock-paper-scissors.md b/curriculum/challenges/arabic/11-machine-learning-with-python/machine-learning-with-python-projects/rock-paper-scissors.md
index 11ba8ef9b4e574..053406bd3403a0 100644
--- a/curriculum/challenges/arabic/11-machine-learning-with-python/machine-learning-with-python-projects/rock-paper-scissors.md
+++ b/curriculum/challenges/arabic/11-machine-learning-with-python/machine-learning-with-python-projects/rock-paper-scissors.md
@@ -12,6 +12,10 @@ For this challenge, you will create a program to play Rock, Paper, Scissors. A p
You will be working on this project with our Replit starter code.
+- Start by importing the project on Replit.
+- Next, you will see a `.replit` window.
+- Select `Use run command` and click the `Done` button.
+
We are still developing the interactive instructional part of the machine learning curriculum. For now, you will have to use other resources to learn how to pass this challenge.
# --instructions--
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
index 99d9fd0cfc9491..bf05e94470b8ec 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md
@@ -19,7 +19,7 @@ dashedName: build-a-survey-form
1. داخل عنصر النموذج، أنت **مطلوب** منك إدخال بريدك الإلكتروني في `input` الذي يحتوي على `id` بقيمة `email`
1. إذا قمت بإدخال بريد إلكتروني غير منسق بشكل صحيح، سترى خطأ HTML5 validation error
1. داخل النموذج، يمكنك إدخال رقم في حقل `input` الذي يحتوي على معرف `id` بقيمة `number`
-1. إذا قمت بإدخال رمز ليس رقما في حقل إدخال الرقم، سترى خطأ HTML5 validation error
+1. لا ينبغي أن يقبل input رقم غير حقيقي، إما عن طريق منعك من الكتابة عليها أو عن طريق عرض خطأ في التحقق من صحة HTML5 (اعتمادا على متصفحك).
1. إذا قمت بإدخال أرقام خارج نطاق حقل إدخال الرقم، التي تم تعريفها بواسطة سمات `min` و `max`، سترى خطأ HTML5 validation error
1. بالنسبة لحقول الاسم والبريد الإلكتروني وإدخال الأرقام ، يمكنك رؤية عناصر `label` المقابلة في النموذج، التي تصف الغرض من كل حقل بالـ id's التالية: `id="name-label"` و `id="email-label"` و `id="number-label"`
1. بالنسبة لحقول الاسم والبريد الإلكتروني والرقم، يمكنك أن ترى الـ placeholder text الذي يعطي وصفا أو تعليمات لكل حقل
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613297a923965e0703b64796.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613297a923965e0703b64796.md
index 9e450b924b7645..ef2f241128c699 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613297a923965e0703b64796.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613297a923965e0703b64796.md
@@ -1,6 +1,6 @@
---
id: 613297a923965e0703b64796
-title: الخطوة الثانية
+title: الخطوة 2
challengeType: 0
dashedName: step-2
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md
index 8733579a2d404a..f7f79efd9f24f3 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md
@@ -1,6 +1,6 @@
---
id: 61329b210dac0b08047fd6ab
-title: الخطوة ٣
+title: الخطوة 3
challengeType: 0
dashedName: step-3
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133acc353338c0bba9cb553.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133acc353338c0bba9cb553.md
index 6c0554d882dbcd..236756f1181254 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133acc353338c0bba9cb553.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133acc353338c0bba9cb553.md
@@ -1,6 +1,6 @@
---
id: 6133acc353338c0bba9cb553
-title: الخطوة ٥
+title: الخطوة 5
challengeType: 0
dashedName: step-5
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md
index 142626b527bafd..2ef7947512dc97 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md
@@ -1,6 +1,6 @@
---
id: 6133d11ef548f51f876149e3
-title: الخطوة ٦
+title: الخطوة 6
challengeType: 0
dashedName: step-6
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e2546d0594208229ada50.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e2546d0594208229ada50.md
index 96149bec6727fb..53861ecc849232 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e2546d0594208229ada50.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e2546d0594208229ada50.md
@@ -1,6 +1,6 @@
---
id: 613e2546d0594208229ada50
-title: الخطوة ٧
+title: الخطوة 7
challengeType: 0
dashedName: step-7
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e275749ebd008e74bb62e.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e275749ebd008e74bb62e.md
index e619ec59befc7c..1d6c7b5301ab63 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e275749ebd008e74bb62e.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/613e275749ebd008e74bb62e.md
@@ -1,6 +1,6 @@
---
id: 613e275749ebd008e74bb62e
-title: الخطوة ٨
+title: الخطوة 8
challengeType: 0
dashedName: step-8
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140827cff96e906bd38fc2b.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140827cff96e906bd38fc2b.md
index 1756bf4e399122..903a9554405fad 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140827cff96e906bd38fc2b.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140827cff96e906bd38fc2b.md
@@ -1,6 +1,6 @@
---
id: 6140827cff96e906bd38fc2b
-title: الخطوة ٩
+title: الخطوة 9
challengeType: 0
dashedName: step-9
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140883f74224508174794c0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140883f74224508174794c0.md
index 5b70a2fc6efb04..2ceaa8c40cbcf7 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140883f74224508174794c0.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6140883f74224508174794c0.md
@@ -1,6 +1,6 @@
---
id: 6140883f74224508174794c0
-title: الخطوة ١٠
+title: الخطوة 10
challengeType: 0
dashedName: step-10
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408e4ae3e35d08feb260eb.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408e4ae3e35d08feb260eb.md
index 12e71fb4efb2b2..34b6634147e1cf 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408e4ae3e35d08feb260eb.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408e4ae3e35d08feb260eb.md
@@ -1,6 +1,6 @@
---
id: 61408e4ae3e35d08feb260eb
-title: الخطوة ١١
+title: الخطوة 11
challengeType: 0
dashedName: step-11
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408f155e798909b6908712.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408f155e798909b6908712.md
index 874a5ba78efc96..6925c6827266fc 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408f155e798909b6908712.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61408f155e798909b6908712.md
@@ -1,6 +1,6 @@
---
id: 61408f155e798909b6908712
-title: الخطوة ١٢
+title: الخطوة 12
challengeType: 0
dashedName: step-12
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614090d5a22b6f0a5a6b464c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614090d5a22b6f0a5a6b464c.md
index 73854a5a328265..c1dc11d1481b2b 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614090d5a22b6f0a5a6b464c.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614090d5a22b6f0a5a6b464c.md
@@ -1,6 +1,6 @@
---
id: 614090d5a22b6f0a5a6b464c
-title: الخطوة ١٣
+title: الخطوة 13
challengeType: 0
dashedName: step-13
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md
index dc9d279f93a3ac..9a3b8519bf0d93 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md
@@ -1,6 +1,6 @@
---
id: 6141fabd6f75610664e908fd
-title: الخطوة ١٤
+title: الخطوة 14
challengeType: 0
dashedName: step-14
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md
index 8934c5566756e1..f2fc524bf70116 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md
@@ -1,6 +1,6 @@
---
id: 6141fed65b61320743da5894
-title: خطوة ١٥
+title: الخطوة 15
challengeType: 0
dashedName: step-15
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md
index 5d973a8a5a9a97..14a22bb7136df7 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md
@@ -1,6 +1,6 @@
---
id: 614202874ca576084fca625f
-title: الخطوة ١٦
+title: الخطوة 16
challengeType: 0
dashedName: step-16
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md
index 386b4dd83d19a0..38bca467f6f5d8 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md
@@ -1,6 +1,6 @@
---
id: 614206033d366c090ca7dd42
-title: الخطوة ١٧
+title: الخطوة 17
challengeType: 0
dashedName: step-17
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61435e3c0679a306c20f1acc.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61435e3c0679a306c20f1acc.md
index ef109b3ec5fbc4..b8d73ab85d0f24 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61435e3c0679a306c20f1acc.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61435e3c0679a306c20f1acc.md
@@ -1,6 +1,6 @@
---
id: 61435e3c0679a306c20f1acc
-title: الخطوة ١٨
+title: الخطوة 18
challengeType: 0
dashedName: step-18
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143610161323a081b249c19.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143610161323a081b249c19.md
index 3fc12168741641..116f3e59fa93fe 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143610161323a081b249c19.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143610161323a081b249c19.md
@@ -1,6 +1,6 @@
---
id: 6143610161323a081b249c19
-title: الخطوة ١٩
+title: الخطوة 19
challengeType: 0
dashedName: step-19
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143639d5eddc7094161648c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143639d5eddc7094161648c.md
index 7c7811ac594c99..e142dd6f683f04 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143639d5eddc7094161648c.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143639d5eddc7094161648c.md
@@ -1,6 +1,6 @@
---
id: 6143639d5eddc7094161648c
-title: الخطوة ٢٠
+title: الخطوة 20
challengeType: 0
dashedName: step-20
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143908b6aafb00a659ca189.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143908b6aafb00a659ca189.md
index 479da772cbf455..1e1d4428b53d15 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143908b6aafb00a659ca189.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143908b6aafb00a659ca189.md
@@ -1,6 +1,6 @@
---
id: 6143908b6aafb00a659ca189
-title: الخطوة ٢١
+title: الخطوة 21
challengeType: 0
dashedName: step-21
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md
index 660e00ac2183f4..4c76d78f016eec 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md
@@ -1,6 +1,6 @@
---
id: 6143920c8eafb00b735746ce
-title: الخطوة ٢٢
+title: الخطوة 22
challengeType: 0
dashedName: step-22
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143931a113bb80c45546287.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143931a113bb80c45546287.md
index b35e4d4bbf8f3f..12bfdd2c0a25e5 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143931a113bb80c45546287.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143931a113bb80c45546287.md
@@ -1,6 +1,6 @@
---
id: 6143931a113bb80c45546287
-title: الخطوة ٢٣
+title: الخطوة 23
challengeType: 0
dashedName: step-23
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614394fb41985e0d2012a93e.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614394fb41985e0d2012a93e.md
index 8ae3e5c361bebc..45d20ecf1469a1 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614394fb41985e0d2012a93e.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614394fb41985e0d2012a93e.md
@@ -1,6 +1,6 @@
---
id: 614394fb41985e0d2012a93e
-title: الخطوة ٢٤
+title: الخطوة 24
challengeType: 0
dashedName: step-24
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143956ed76ed60e012faa51.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143956ed76ed60e012faa51.md
index 45ec5b15c3b97b..a2a4c1e4e85e02 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143956ed76ed60e012faa51.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143956ed76ed60e012faa51.md
@@ -1,6 +1,6 @@
---
id: 6143956ed76ed60e012faa51
-title: خطوة ٢٥
+title: الخطوة 25
challengeType: 0
dashedName: step-25
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614396f7ae83f20ea6f9f4b3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614396f7ae83f20ea6f9f4b3.md
index e63aedd46feefd..a70615ad6e990b 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614396f7ae83f20ea6f9f4b3.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614396f7ae83f20ea6f9f4b3.md
@@ -1,6 +1,6 @@
---
id: 614396f7ae83f20ea6f9f4b3
-title: الخطوة ٢٦
+title: الخطوة 26
challengeType: 0
dashedName: step-26
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143cb26f7edff2dc28f7da5.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143cb26f7edff2dc28f7da5.md
index f8eb195500284f..48dbc8a3638cb2 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143cb26f7edff2dc28f7da5.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143cb26f7edff2dc28f7da5.md
@@ -1,6 +1,6 @@
---
id: 6143cb26f7edff2dc28f7da5
-title: خطوة ٢٧
+title: الخطوة 27
challengeType: 0
dashedName: step-27
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144e818fd5ea704fe56081d.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144e818fd5ea704fe56081d.md
index f798c25ea85669..a93fef3f29c8f5 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144e818fd5ea704fe56081d.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144e818fd5ea704fe56081d.md
@@ -1,6 +1,6 @@
---
id: 6144e818fd5ea704fe56081d
-title: الخطوة ٢٨
+title: الخطوة 28
challengeType: 0
dashedName: step-28
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144f8dc6849e405dd8bb829.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144f8dc6849e405dd8bb829.md
index 3562e1ed1d63ca..2f7ad2b3029f1a 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144f8dc6849e405dd8bb829.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6144f8dc6849e405dd8bb829.md
@@ -1,6 +1,6 @@
---
id: 6144f8dc6849e405dd8bb829
-title: الخطوة ٢٩
+title: الخطوة 29
challengeType: 0
dashedName: step-29
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145e6eeaa66c605eb087fe9.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145e6eeaa66c605eb087fe9.md
index 45f7601bff6034..a5a8afa923b344 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145e6eeaa66c605eb087fe9.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145e6eeaa66c605eb087fe9.md
@@ -1,6 +1,6 @@
---
id: 6145e6eeaa66c605eb087fe9
-title: الخطوة ٣٠
+title: الخطوة 30
challengeType: 0
dashedName: step-30
---
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md
index 4eb04ace0442e5..6efdb63b87e498 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md
@@ -35,10 +35,10 @@ assert.exists(document.querySelector('section:last-of-type + button') || documen
assert.exists(document.querySelector('button[type="submit"]') || document.querySelector('form > input[type="submit"]'));
```
-يجب أن يعرض submit النص `Submit`.
+يجب أن يعرض زر الإرسال (submit) نص `Send`.
```js
-assert.equal(document.querySelector('button[type="submit"]')?.textContent ?? document.querySelector('input[type="submit"]')?.value, 'Submit');
+assert.equal(document.querySelector('button[type="submit"]')?.textContent ?? document.querySelector('input[type="submit"]')?.value, 'Send');
```
# --seed--
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f829ac6a920ebf5797d7.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f829ac6a920ebf5797d7.md
index b08fdc8ff30228..7e212d75f5a054 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f829ac6a920ebf5797d7.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f829ac6a920ebf5797d7.md
@@ -138,7 +138,7 @@ assert.exists(document.querySelector('footer > address'));
-
+
--fcc-editable-region--
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f8f8bcd4370f6509078e.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f8f8bcd4370f6509078e.md
index 3cdcf08901d47f..a241fb4217f5d1 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f8f8bcd4370f6509078e.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f8f8bcd4370f6509078e.md
@@ -137,7 +137,7 @@ assert.equal(document.querySelector('address')?.innerText, 'freeCodeCamp\nSan Fr
-
+
--fcc-editable-region--
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fb5018cb5b100cb2a88c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fb5018cb5b100cb2a88c.md
index 54a057025e3a5d..df2e6c0be50cc5 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fb5018cb5b100cb2a88c.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fb5018cb5b100cb2a88c.md
@@ -145,7 +145,7 @@ assert.equal(document.querySelector('address')?.innerHTML?.match(/freeCodeCamp/g
-
+
--fcc-editable-region--
diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fc3707fc3310c277f5c8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fc3707fc3310c277f5c8.md
index 64afb451a1c81d..a5fe55ac2ec2af 100644
--- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fc3707fc3310c277f5c8.md
+++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145fc3707fc3310c277f5c8.md
@@ -170,7 +170,7 @@ assert.equal(display, 'block');
-
+