fix: use lodash-es in the client (#41931)

This commit is contained in:
Oliver Eyton-Williams
2021-04-28 23:11:20 +02:00
committed by GitHub
parent db369fbed1
commit 9be2fb9a10
37 changed files with 95 additions and 43 deletions

View File

@ -43,10 +43,6 @@
"react-bootstrap": {
"transform": "react-bootstrap/lib/${member}",
"preventFullImport": true
},
"lodash": {
"transform": "lodash/${member}",
"preventFullImport": true
}
}
],

View File

@ -2,6 +2,8 @@ const env = require('../config/env');
const webpack = require('webpack');
const { createFilePath } = require('gatsby-source-filesystem');
// TODO: ideally we'd remove lodash and just use lodash-es, but we can't require
// es modules here.
const uniq = require('lodash/uniq');
const { blockNameify } = require('../utils/block-nameify');
@ -231,10 +233,6 @@ exports.onCreateBabelConfig = ({ actions }) => {
'@freecodecamp/react-bootstrap': {
transform: '@freecodecamp/react-bootstrap/lib/${member}',
preventFullImport: true
},
lodash: {
transform: 'lodash/${member}',
preventFullImport: true
}
}
});

View File

@ -6,7 +6,8 @@ module.exports = {
'^(?!.*\\.module\\.css$).*\\.css$': '<rootDir>/src/__mocks__/styleMock.js',
// CSS Modules - match files that end with 'module.css'
'\\.module\\.css$': 'identity-obj-proxy',
'react-i18next': '<rootDir>/src/__mocks__/react-i18nextMock.js'
'react-i18next': '<rootDir>/src/__mocks__/react-i18nextMock.js',
'^lodash-es$': 'lodash'
},
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/.cache/'],
globals: {

View File

@ -8,10 +8,6 @@ const babelOptions = {
'@freecodecamp/react-bootstrap': {
transform: '@freecodecamp/react-bootstrap/lib/${member}',
preventFullImport: true
},
lodash: {
transform: 'lodash/${member}',
preventFullImport: true
}
}
]

View File

@ -5236,6 +5236,15 @@
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ=="
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@ -9765,6 +9774,12 @@
"typedarray-to-buffer": "^3.1.5"
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"filesize": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz",
@ -17136,6 +17151,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
@ -18133,6 +18153,12 @@
"resolved": "https://registry.npmjs.org/name-all-modules-plugin/-/name-all-modules-plugin-1.0.1.tgz",
"integrity": "sha1-Cr+2rYNXGLn7Te8GdOBmV6lUN1w="
},
"nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
"optional": true
},
"nanoid": {
"version": "3.1.22",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
@ -25479,7 +25505,11 @@
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"optional": true
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
},
"globby": {
"version": "6.1.0",

View File

@ -81,6 +81,7 @@
"i18next": "19.9.2",
"jquery": "3.6.0",
"lodash": "4.17.21",
"lodash-es": "4.17.21",
"monaco-editor": "0.22.3",
"nanoid": "3.1.22",
"path-browserify": "1.0.1",

View File

@ -32,7 +32,7 @@ import envData from '../../../config/env.json';
import RedirectHome from '../components/RedirectHome';
import { Loader, Spacer } from '../components/helpers';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
import { User } from '../redux/propTypes';
const { clientLocale } = envData;

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
import Loader from '../components/helpers/Loader';
import {

View File

@ -6,7 +6,7 @@ import { maybeUrlRE } from '../utils';
import { Spacer, Link } from '../components/helpers';
import { projectMap, legacyProjectMap } from '../resources/certAndProjectMap';
import ProjectModal from '../components/SolutionViewer/ProjectModal';
import { find, first } from 'lodash';
import { find, first } from 'lodash-es';
import { Trans, useTranslation } from 'react-i18next';
const propTypes = {

View File

@ -1,6 +1,6 @@
import chai from 'chai';
import '@babel/polyfill';
import __toString from 'lodash/toString';
import { toString as __toString } from 'lodash-es';
import { format as __format } from '../../utils/format';
import curriculumHelpers from '../../utils/curriculum-helpers';

View File

@ -1,5 +1,5 @@
import React from 'react';
import { kebabCase } from 'lodash';
import { kebabCase } from 'lodash-es';
import normalizeUrl from 'normalize-url';
import PropTypes from 'prop-types';
import {

View File

@ -1,6 +1,6 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { curry } from 'lodash';
import { curry } from 'lodash-es';
import { createSelector } from 'reselect';
import { connect } from 'react-redux';
import { Row, Col } from '@freecodecamp/react-bootstrap';

View File

@ -1,6 +1,6 @@
import React, { Component, useMemo } from 'react';
import PropTypes from 'prop-types';
import { reverse, sortBy } from 'lodash';
import { reverse, sortBy } from 'lodash-es';
import {
Button,
Modal,

View File

@ -5,7 +5,7 @@ import { bindActionCreators } from 'redux';
import { createSelector } from 'reselect';
import { SearchBox } from 'react-instantsearch-dom';
import { HotKeys, ObserveKeys } from 'react-hotkeys';
import { isEqual } from 'lodash';
import { isEqual } from 'lodash-es';
import { withTranslation } from 'react-i18next';
import { searchPageUrl } from '../../../utils/algolia-locale-setup';

View File

@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { connectStateResults, connectHits } from 'react-instantsearch-dom';
import isEmpty from 'lodash/isEmpty';
import { isEmpty } from 'lodash-es';
import { useTranslation } from 'react-i18next';
import { searchPageUrl } from '../../../utils/algolia-locale-setup';

View File

@ -5,7 +5,7 @@ import {
connectStateResults,
connectAutoComplete
} from 'react-instantsearch-dom';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
import EmptySearch from './EmptySearch';
import NoResults from './NoResults';

View File

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { find, first, values, isString } from 'lodash';
import { find, first, values, isString } from 'lodash-es';
import {
Table,
Button,

View File

@ -8,7 +8,7 @@ import {
FormControl,
HelpBlock
} from '@freecodecamp/react-bootstrap';
import { findIndex, find, isEqual } from 'lodash';
import { findIndex, find, isEqual } from 'lodash-es';
import isURL from 'validator/lib/isURL';
import { withTranslation } from 'react-i18next';

View File

@ -16,7 +16,7 @@ import {
} from '@freecodecamp/react-bootstrap';
import Helmet from 'react-helmet';
import isEmail from 'validator/lib/isEmail';
import { isString } from 'lodash';
import { isString } from 'lodash-es';
import { withTranslation } from 'react-i18next';
import { Spacer } from '../components/helpers';

View File

@ -1,6 +1,6 @@
import { navigate } from 'gatsby';
import { takeEvery, put } from 'redux-saga/effects';
import { isError } from 'lodash';
import { isError } from 'lodash-es';
import { isHandledError, unwrapHandledError } from '../utils/handled-error';
import { reportClientSideError } from '../utils/report-error';

View File

@ -1,5 +1,5 @@
import { createAction, handleActions } from 'redux-actions';
import { uniqBy } from 'lodash';
import { uniqBy } from 'lodash-es';
import store from 'store';
import { createTypes, createAsyncTypes } from '../utils/createTypes';

View File

@ -1,7 +1,7 @@
import React, { Component, Fragment } from 'react';
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
import PropTypes from 'prop-types';
import { first } from 'lodash';
import { first } from 'lodash-es';
import EditorTabs from './EditorTabs';
import ActionRow from './ActionRow';
import envData from '../../../../../config/env.json';

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import noop from 'lodash/noop';
import { noop } from 'lodash-es';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Button, Modal } from '@freecodecamp/react-bootstrap';

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import sanitizeHtml from 'sanitize-html';
import './output.css';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
const propTypes = {
defaultOutput: PropTypes.string,

View File

@ -6,7 +6,7 @@ import {
partial,
stubTrue,
template as _template
} from 'lodash';
} from 'lodash-es';
import {
compileHeadTail,

View File

@ -1,4 +1,4 @@
import { cond, identity, stubTrue, conforms } from 'lodash';
import { cond, identity, stubTrue, conforms } from 'lodash-es';
const HTML$JSReg = /html|js/;

View File

@ -8,7 +8,7 @@ import {
overSome,
partial,
stubTrue
} from 'lodash';
} from 'lodash-es';
import protect from '@freecodecamp/loop-protect';

View File

@ -11,7 +11,7 @@ import {
cancel
} from 'redux-saga/effects';
import { channel } from 'redux-saga';
import escape from 'lodash/escape';
import { escape } from 'lodash-es';
import i18next from 'i18next';
import {

View File

@ -14,7 +14,7 @@ import { createCurrentChallengeSaga } from './current-challenge-saga';
import { challengeTypes } from '../../../../utils/challengeTypes';
import { getTargetEditor } from '../utils/getTargetEditor';
import { completedChallengesSelector } from '../../../redux';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
export const ns = 'challenge';
export const backendNS = 'backendChallenge';

View File

@ -1,4 +1,4 @@
import { toString, flow } from 'lodash';
import { toString, flow } from 'lodash-es';
import { format } from '../../../utils/format';
// we use two different frames to make them all essentially pure functions

View File

@ -1,5 +1,5 @@
import { toSortedArray } from '../../../../../utils/sort-files';
import { isEmpty } from 'lodash';
import { isEmpty } from 'lodash-es';
export function getTargetEditor(challengeFiles) {
if (isEmpty(challengeFiles)) return null;

View File

@ -2,7 +2,7 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import Helmet from 'react-helmet';
import { graphql } from 'gatsby';
import { uniq } from 'lodash';
import { uniq } from 'lodash-es';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { bindActionCreators } from 'redux';

View File

@ -1,4 +1,4 @@
import { has } from 'lodash';
import { has } from 'lodash-es';
import standardErrorMessage from './standardErrorMessage';
import reportedErrorMessage from './reportedErrorMessage';

View File

@ -1,5 +1,5 @@
/* global expect */
import { isObject } from 'lodash';
import { isObject } from 'lodash-es';
import sinon from 'sinon';
import {
isHandledError,

View File

@ -5905,6 +5905,27 @@
}
}
},
"mock-require": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz",
"integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==",
"dev": true,
"requires": {
"get-caller-file": "^1.0.2",
"normalize-path": "^2.1.1"
},
"dependencies": {
"normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
"dev": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
}
}
}
},
"morgan": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",

View File

@ -55,6 +55,7 @@
"live-server": "1.2.1",
"lodash": "4.17.21",
"mocha": "8.3.2",
"mock-require": "3.0.3",
"puppeteer": "8.0.0",
"readdirp": "3.6.0",
"rehype": "11.0.0",

View File

@ -17,6 +17,13 @@ require('@babel/register')({
only: [clientPath]
});
const mockRequire = require('mock-require');
const lodash = require('lodash');
// lodash-es can't easily be used in node environments, so we just mock it out
// for the original lodash in testing.
mockRequire('lodash-es', lodash);
const createPseudoWorker = require('./utils/pseudo-worker');
const {
default: createWorker
@ -24,7 +31,8 @@ const {
const { assert, AssertionError } = require('chai');
const Mocha = require('mocha');
const { flatten, isEmpty, cloneDeep, isEqual } = require('lodash');
const { flatten, isEmpty, cloneDeep, isEqual } = lodash;
const { getLines } = require('../../utils/get-lines');
const jsdom = require('jsdom');