Google Analytics cookies
This site uses Google Analytics which is one of the most widespread and trusted analytics solutions
- on the web, as well as Hotjar in order to help us understand how you use the site and ways that we can improve your
+ on the web in order to help us understand how you use the site and ways that we can improve your
experience. These cookies may track things such as how long you spend on the site and the pages that you visit so we
can continue to produce engaging content.
For more information on Google Analytics cookies, see the official {
let q = keyphrase.toLowerCase().trim();
if (q.length <= 1) return [];
@@ -34,17 +34,34 @@ const searchByKeyphrase = (keyphrase, searchIndex) => {
return snippet;
})
.filter(snippet => snippet.score > 0.3)
- .sort((a, b) => b.score - a.score)
- .slice(0, 50);
+ .sort((a, b) => b.score - a.score);
}
}
return results;
};
+const filterResultsByType = (type, searchResults) => {
+ switch (type) {
+ case 'collections':
+ return searchResults.filter(r => !r.expertise);
+ case 'snippets':
+ return searchResults.filter(
+ r => r.expertise && r.expertise.toLowerCase() !== 'article'
+ );
+ case 'articles':
+ return searchResults.filter(
+ r => r.expertise && r.expertise.toLowerCase() === 'article'
+ );
+ default:
+ return searchResults;
+ }
+};
+
export const actionTypes = {
pushNewQuery: 'pushNewQuery',
initializeIndex: 'initializeIndex',
searchByKeyphrase: 'searchByKeyphrase',
+ filterResultsByType: 'filterResultsByType',
};
const reducer = (state, action) => {
@@ -60,10 +77,39 @@ const reducer = (state, action) => {
...state,
searchIndex: action.index,
};
- case actionTypes.searchByKeyphrase:
+ case actionTypes.searchByKeyphrase: {
+ const searchResults = searchByKeyphrase(
+ action.keyphrase,
+ state.searchIndex
+ );
+ const availableFilters = {
+ All: true,
+ Snippets: searchResults.some(
+ r => r.expertise && r.expertise.toLowerCase() !== 'article'
+ ),
+ Articles: searchResults.some(
+ r => r.expertise && r.expertise.toLowerCase() === 'article'
+ ),
+ Collections: searchResults.some(r => !r.expertise),
+ };
+ return {
+ ...state,
+ searchResults,
+ filteredResults: searchResults.slice(0, SEARCH_RESULTS_COUNT),
+ typeFilter: 'all',
+ availableFilters: Object.entries(availableFilters)
+ .filter(([key, value]) => value)
+ .map(([key]) => key),
+ };
+ }
+ case actionTypes.filterResultsByType:
return {
...state,
- searchResults: searchByKeyphrase(action.keyphrase, state.searchIndex),
+ filteredResults: filterResultsByType(
+ action.resultType,
+ state.searchResults
+ ).slice(0, SEARCH_RESULTS_COUNT),
+ typeFilter: action.resultType,
};
default:
return state;
@@ -77,7 +123,6 @@ const {
useStateDispatch: useSearch,
} = createStateProvider({
initialState,
- persistKey,
reducer,
stateContextName: 'SearchState',
dispatchContextName: 'SearchDispatch',
diff --git a/src/styles/_colors.scss b/src/styles/_colors.scss
index 2b3f85666..034769dc2 100644
--- a/src/styles/_colors.scss
+++ b/src/styles/_colors.scss
@@ -6,6 +6,11 @@
// Page background
--clr-bg: hsl(240, 49%, 7%);
+ // Brand primary
+ --clr-primary-050: hsl(217, 82%, 77%);
+ --clr-primary-100: hsl(217, 98%, 66%);
+ --clr-primary-200: hsl(224, 97%, 49%);
+
// Navbar
--clr-navbar-bg: hsl(252, 22%, 5%);
@@ -19,7 +24,6 @@
--clr-search-results-border: hsla(0, 0%, 100%, 0.12);
// Buttons & toggles
- --clr-btn-bg: hsl(239, 97%, 61%);
--clr-tgl-fg: hsl(240, 4%, 84%);
--clr-tgl-bg: hsl(235, 7%, 39%);
--clr-tgl-fg-active: hsl(240, 82%, 87%);
@@ -29,16 +33,12 @@
--clr-exp-beginner: hsl(89, 64%, 46%);
--clr-exp-intermediate: hsl(42, 100%, 50%);
--clr-exp-advanced: hsl(1, 84%, 59%);
- --clr-exp-blog: hsl(216, 100%, 63%);
-
- // Card actions
- --clr-action: hsl(278, 36%, 73%);
+ --clr-exp-article: hsl(216, 100%, 63%);
// Snippet Preview (CSS snippet cards)
--clr-snippet-preview-bg: hsl(240, 26%, 7%);
- // Blog snippet cards
+ // Article snippet cards
--clr-quote-border: hsl(223, 32%, 64%);
--clr-table-border: hsl(235, 7%, 39%);
- --clr-img-credit-bg :hsla(240, 27%, 7%, 0.84);
}
diff --git a/src/styles/_fonts.scss b/src/styles/_fonts.scss
index b931c21e2..3b8b4da4d 100644
--- a/src/styles/_fonts.scss
+++ b/src/styles/_fonts.scss
@@ -25,35 +25,10 @@
}
@font-face {
font-family: 'Inter';
- font-style: normal;
- font-weight: 400;
- font-display: swap;
- src: local('Inter'), local('Inter-Regular'), url('/assets/Inter-Regular.woff2') format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 400;
+ font-weight: 100 1000;
font-display: swap;
- src: local('Inter Italic'), local('Inter-Italic'), url('/assets/Inter-Italic.woff2') format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 500;
- font-display: swap;
- src: local('Inter Medium'), local('Inter-Medium'), url('/assets/Inter-Medium.woff2') format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 600;
- font-display: swap;
- src: local('Inter SemiBold'), local('Inter-SemiBold'), url('/assets/Inter-SemiBold.woff2') format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+ src: url('/assets/Inter.var.woff2') format('woff2 supports variations'),
+ url('/assets/Inter.var.woff2') format('woff2-variations');
}
@font-face {
font-family: 'Raleway';
diff --git a/src/styles/_functions.scss b/src/styles/_functions.scss
index c8c8934ce..bb0ed6d8b 100644
--- a/src/styles/_functions.scss
+++ b/src/styles/_functions.scss
@@ -10,8 +10,4 @@
@function generate-icon-background($icon-name, $stroke-color, $fill-color: 'none', $stroke-width: 2, $size: 24) {
$stroke: url-friendly-color($stroke-color);
$fill: url-friendly-color($fill-color);
-
- @if $icon-name == "dartlang" {
- @return url("data:image/svg+xml,%3Csvg width='"+$size+"' height='"+$size+"' viewBox='0 0 96 96' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M19.578 76.422L3.155 59.998C1.207 58.001 0 55.178 0 52.418 0 51.141.72 49.143 1.263 48l15.16-31.576 3.155 59.998z' fill='%2301579B'/%3E%3Cpath d='M75.794 19.578L59.37 3.155C57.937 1.715 54.952 0 52.425 0c-2.173 0-4.305.438-5.681 1.263L16.43 16.423l59.364 3.155zM39.157 96h39.791V78.948L49.263 69.47l-27.158 9.478L39.157 96z' fill='%2340C4FF'/%3E%3Cpath d='M16.424 67.578c0 5.068.635 6.31 3.154 8.844l2.527 2.526h56.843L51.162 47.372 16.424 16.424v51.154z' fill='%2329B6F6'/%3E%3Cpath d='M66.95 16.416H16.424l62.524 62.525H96V39.785L75.787 19.57c-2.838-2.844-5.357-3.155-8.837-3.155z' fill='%2301579B'/%3E%3Cpath opacity='.2' d='M20.213 77.05c-2.526-2.534-3.154-5.032-3.154-9.472V17.052l-.629-.628v51.154c-.007 4.44-.007 5.668 3.784 9.472l1.891 1.891-1.892-1.891z' fill='%23fff'/%3E%3Cpath opacity='.2' d='M95.372 39.157v39.156H78.32l.628.635H96V39.785l-.628-.628z' fill='%23263238'/%3E%3Cpath opacity='.2' d='M75.794 19.578c-3.134-3.133-5.696-3.154-9.472-3.154H16.43l.629.628h49.263c1.885 0 6.641-.318 9.472 2.526z' fill='%23fff'/%3E%3Cpath opacity='.2' d='M95.372 39.157L75.794 19.578 59.37 3.155C57.937 1.715 54.952 0 52.425 0c-2.173 0-4.305.438-5.681 1.263L16.43 16.423 1.27 48C.727 49.15.007 51.148.007 52.418c0 2.76 1.214 5.576 3.155 7.58l15.132 15.026c.36.445.783.897 1.284 1.398l.628.628 1.892 1.891 16.423 16.424.629.628h39.784V78.94h17.052V39.785l-.614-.628z' fill='url(%23paint0_radial)'/%3E%3Cdefs%3E%3CradialGradient id='paint0_radial' cx='0' cy='0' r='1' gradientUnits='userSpaceOnUse' gradientTransform='translate(47.996 47.998) scale(47.9929)'%3E%3Cstop stop-color='%23fff' stop-opacity='.1'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3C/svg%3E");
- }
}
diff --git a/src/styles/_icons.scss b/src/styles/_icons.scss
index f6c2be165..d93bf9619 100644
--- a/src/styles/_icons.scss
+++ b/src/styles/_icons.scss
@@ -1,6 +1,6 @@
@font-face {
font-family: "icons";
- src: url("../../assets/icons.woff2?24b22a509b7ef7b75bd38af25460adc9") format("woff2");
+ src: url("../../assets/icons.woff2?8e2188a8340c97e1472ef5ee189f6cf9") format("woff2");
}
.icon:before {
@@ -38,56 +38,47 @@
.icon.icon-codepen:before {
content: "\f108";
}
-.icon.icon-csharp:before {
- content: "\f109";
-}
.icon.icon-css:before {
- content: "\f10a";
+ content: "\f109";
}
.icon.icon-deduck:before {
- content: "\f10b";
+ content: "\f10a";
}
.icon.icon-git:before {
- content: "\f10c";
+ content: "\f10b";
}
.icon.icon-github:before {
- content: "\f10d";
-}
-.icon.icon-golang:before {
- content: "\f10e";
+ content: "\f10c";
}
.icon.icon-home:before {
- content: "\f10f";
+ content: "\f10d";
}
.icon.icon-js:before {
- content: "\f110";
+ content: "\f10e";
}
.icon.icon-list:before {
- content: "\f111";
+ content: "\f10f";
}
.icon.icon-node:before {
- content: "\f112";
-}
-.icon.icon-php:before {
- content: "\f113";
+ content: "\f110";
}
.icon.icon-python:before {
- content: "\f114";
+ content: "\f111";
}
.icon.icon-react:before {
- content: "\f115";
+ content: "\f112";
}
.icon.icon-search:before {
- content: "\f116";
+ content: "\f113";
}
.icon.icon-share:before {
- content: "\f117";
+ content: "\f114";
}
.icon.icon-star:before {
- content: "\f118";
+ content: "\f115";
}
.icon.icon-twitter:before {
- content: "\f119";
+ content: "\f116";
}
.card-icon,
diff --git a/src/styles/_layout.scss b/src/styles/_layout.scss
index b282e47bd..4a3c9cadc 100644
--- a/src/styles/_layout.scss
+++ b/src/styles/_layout.scss
@@ -1,9 +1,11 @@
-// Display and flex
+// Display, flex, grid
.inline-block { display: inline-block; }
.flex { display: flex; }
+.grid { display: grid; }
.flex-col { flex-direction: column; }
.j-center { justify-content: center; }
.a-center { align-items: center; }
+.flex-none { flex: none; }
// Margin
.m-0 { margin: 0; }
diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss
index 4e280b58c..c1c846e11 100644
--- a/src/styles/_reset.scss
+++ b/src/styles/_reset.scss
@@ -14,7 +14,7 @@ html, * {
}
* {
font-size: var(--font-sm);
- font-weight: 400;
+ font-weight: 350;
}
// Apply fixes and defaults as necessary for modern browsers only
a, b, em, i, q, span, strong, u {
@@ -91,7 +91,7 @@ blockquote {
box-shadow: inset 4px 0 0 0 var(--clr-quote-border);
font-style: italic;
line-height: 2;
- font-weight: 400;
+ font-weight: 350;
}
// Style tabular content
table {
diff --git a/src/styles/type/_anchor.scss b/src/styles/type/_anchor.scss
index e6c314a19..6f97b2658 100644
--- a/src/styles/type/_anchor.scss
+++ b/src/styles/type/_anchor.scss
@@ -1,13 +1,8 @@
-// Colors
-:root {
- --clr-link: hsl(217, 82%, 77%);
-}
-
a {
text-decoration: none;
&:link, &:visited {
- color: var(--clr-link);
+ color: var(--clr-primary-050);
}
&:hover, &:focus {
@@ -17,8 +12,14 @@ a {
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
-}
+ &.inherit {
+
+ &:link, &:visited {
+ color: inherit;
+ }
+ }
+}
@keyframes animated-underline {
0% {
diff --git a/src/styles/type/_code.scss b/src/styles/type/_code.scss
index cc060e408..a1bb49943 100644
--- a/src/styles/type/_code.scss
+++ b/src/styles/type/_code.scss
@@ -83,7 +83,7 @@ p > code, a > code {
a > code {
&, &[class*="language-"] {
- color: var(--clr-link);
+ color: var(--clr-primary-050);
}
}
diff --git a/src/styles/type/_colors.scss b/src/styles/type/_colors.scss
index b30809e9b..752fb78c0 100644
--- a/src/styles/type/_colors.scss
+++ b/src/styles/type/_colors.scss
@@ -3,8 +3,19 @@
@mixin generate-text-colors ($txts) {
@each $txt in $txts {
- .txt-#{$txt} {
- color: var(--clr-txt-#{$txt});
+ $txt-name: $txt;
+ @if $txt-name == 050 {
+ $txt-name: '050';
+ }
+
+ .txt-#{$txt-name} {
+ color: var(--clr-txt-#{$txt-name});
+
+ @if $txt != '200' {
+ b, strong {
+ color: var(--clr-txt-#{$txt+50});
+ }
+ }
}
}
}
@@ -17,4 +28,4 @@
--clr-txt-050: hsla(0, 0%, 100%, .64);
}
-@include generate-text-colors(('200', '150', '100', '050'));
+@include generate-text-colors((200, 150, 100, 050));
diff --git a/src/test/fixtures/factories/blockSnippet.js b/src/test/fixtures/factories/blockSnippet.js
index 049dbc40f..309af08c9 100644
--- a/src/test/fixtures/factories/blockSnippet.js
+++ b/src/test/fixtures/factories/blockSnippet.js
@@ -34,7 +34,7 @@ factory
})
.trait('blog', {
body:
- "#### React rendering\n\n- React rendering basics (this blog post)\n- [React rendering optimization](/blog/s/react-rendering-optimization)\n- [React rendering state](/blog/s/react-rendering-state)\n\n\n### Rendering introduction\n\n**Rendering** is the process during which React moves down the component tree starting at the root, looking for all the components flagged for update, asking them to describe their desired UI structure based on the current combination of `props` and `state`. For each flagged component, React will call its `render()` method (for class components) or `FunctionComponent()` (for function components), and save the output produced after converting the JSX result into a plain JS object, using `React.createElement()`.\n\nAfter collecting the render output from the entire component tree, React will diff the new tree (the **virtual DOM**) with the current DOM tree and collect the list of changes that need to be made to the DOM to produce the desired UI structure. After this process, known as **reconciliation**, React applies all the calculated changes to the DOM.\n\n### Render and commit phases\n\nConceptually, this work is divided into two phases:\n\n- **Render phase**: rendering components, calculating changes\n- **Commit phase**: applying the changes to the DOM\n\nAfter the **commit phase** is complete, React will run `componentDidMount` and `componentDidUpdate` lifecycle methods, as well as `useLayoutEffect` and, after a short timeout, `useEffect` hooks.\n\nTwo key takeaways here are the following:\n\n- Rendering is not the same as updating the DOM\n- A component may be rendered without any visible changes\n\n### Rendering reasons\n\nAfter the initial render has completed, there are a few different things that will cause a re-render:\n\n- `this.setState()` (class components)\n- `this.forceUpdate()` (class components)\n- `useState()` setters (function components)\n- `useReducer()` dispatches (function components)\n- `ReactDOM.render()` again (on the root component)\n\n### Rendering behavior\n\nReact's default behavior is to **recursively render all child components inside of it when a parent component is rendered**. This means that it does not care if a component's `props` have changed - as long as the parent component rendered, its children will render unconditionally.\n\nTo put this another way, calling `setState()` in the root component without any other changes, will cause React to re-render every single component in the component tree. Most likely, most of the components will return the exact same render output as the last render, meaning React will not have to make any changes to the DOM, but the rendering and diffing calculations will be performed regardless, taking time and effort.\n\n[Continue on React rendering optimization](/blog/s/react-rendering-optimization)\n\n**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n",
+ "#### React rendering\n\n- React rendering basics (this blog post)\n- [React rendering optimization](/blog/s/react-rendering-optimization)\n- [React rendering state](/blog/s/react-rendering-state)\n\n\n### Rendering introduction\n\n**Rendering** is the process during which React moves down the component tree starting at the root, looking for all the components flagged for update, asking them to describe their desired UI structure based on the current combination of `props` and `state`. For each flagged component, React will call its `render()` method (for class components) or `FunctionComponent()` (for function components), and save the output produced after converting the JSX result into a plain JS object, using `React.createElement()`.\n\nAfter collecting the render output from the entire component tree, React will diff the new tree (the **virtual DOM**) with the current DOM tree and collect the list of changes that need to be made to the DOM to produce the desired UI structure. After this process, known as **reconciliation**, React applies all the calculated changes to the DOM.\n\n### Render and commit phases\n\nConceptually, this work is divided into two phases:\n\n- **Render phase**: rendering components, calculating changes\n- **Commit phase**: applying the changes to the DOM\n\nAfter the **commit phase** is complete, React will run `componentDidMount` and `componentDidUpdate` lifecycle methods, as well as `useLayoutEffect` and, after a short timeout, `useEffect` hooks.\n\nTwo key takeaways here are the following:\n\n- Rendering is not the same as updating the DOM\n- A component may be rendered without any visible changes\n\n### Rendering reasons\n\nAfter the initial render has completed, there are a few different things that will cause a re-render:\n\n- `this.setState()` (class components)\n- `this.forceUpdate()` (class components)\n- `useState()` setters (function components)\n- `useReducer()` dispatches (function components)\n- `ReactDOM.render()` again (on the root component)\n\n### Rendering behavior\n\nReact's default behavior is to **recursively render all child components inside of it when a parent component is rendered**. This means that it does not care if a component's `props` have changed - as long as the parent component rendered, its children will render unconditionally.\n\nTo put this another way, calling `setState()` in the root component without any other changes, will cause React to re-render every single component in the component tree. Most likely, most of the components will return the exact same render output as the last render, meaning React will not have to make any changes to the DOM, but the rendering and diffing calculations will be performed regardless, taking time and effort.\n\n[Continue on React rendering optimization](/blog/s/react-rendering-optimization)\n\n",
title: 'React rendering basics',
type: 'story',
tags: 'react,render',
diff --git a/src/test/fixtures/factories/contentConfig.js b/src/test/fixtures/factories/contentConfig.js
index 57e8f9632..6ee675027 100644
--- a/src/test/fixtures/factories/contentConfig.js
+++ b/src/test/fixtures/factories/contentConfig.js
@@ -33,7 +33,7 @@ factory
dirName: '30blog',
repoUrl: 'https://github.com/30-seconds/30-seconds-blog',
snippetPath: 'blog_posts',
- slug: 'blog',
+ slug: 'articles',
isBlog: true,
iconName: 'blog',
biasPenaltyMultiplier: 1,
diff --git a/src/test/fixtures/factories/snippet.js b/src/test/fixtures/factories/snippet.js
index aebbd3c7f..6c22a57a3 100644
--- a/src/test/fixtures/factories/snippet.js
+++ b/src/test/fixtures/factories/snippet.js
@@ -29,7 +29,7 @@ factory.sequence('words', function* () {
factory.sequence('expertise', function* () {
while (true)
- yield ['Beginner', 'Intermediate', 'Advanced'][
+ yield ['beginner', 'intermediate', 'advanced'][
Math.floor(Math.random() * 3)
];
});
@@ -56,7 +56,7 @@ factory.sequence('url', function* () {
factory
.define('Snippet', () => ({
title: '',
- expertise: 'Intermediate',
+ expertise: 'intermediate',
primaryTag: '',
language: '',
icon: '',
@@ -77,11 +77,11 @@ factory
}))
// Expertise
.trait('expertise', () => ({ expertise: factory.nextFrom('expertise') }))
- .trait('beginner', { expertise: 'Beginner' })
- .trait('intermediate', { expertise: 'Intermediate' })
- .trait('advanced', { expertise: 'Advanced' })
+ .trait('beginner', { expertise: 'beginner' })
+ .trait('intermediate', { expertise: 'intermediate' })
+ .trait('advanced', { expertise: 'advanced' })
// Blog
- .trait('blog', { expertise: 'Blog', icon: 'blog' })
+ .trait('blog', { expertise: 'blog', icon: 'blog' })
// Search
.trait('search result', () => ({ score: Math.random() }));
@@ -139,6 +139,7 @@ factory
description: '',
fullDescription: '',
},
+ actionType: 'copy',
code: {
src: '',
example: '',
@@ -189,6 +190,8 @@ factory
otherLanguages,
},
icon: lang.toLowerCase(),
+ actionType:
+ type === 'css' ? 'cssCodepen' : type === 'react' ? 'codepen' : 'copy',
tags: {
primary: tags[0],
all: tags,
diff --git a/src/test/fixtures/factories/sorter.js b/src/test/fixtures/factories/sorter.js
deleted file mode 100644
index 786cf116a..000000000
--- a/src/test/fixtures/factories/sorter.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import FixtureFactory from '@fixture-factory/fixture-factory';
-
-const factory = new FixtureFactory();
-
-factory
- .define('Sorter', () => ({
- orders: [
- { title: 'Popularity', url: '/list/p/1' },
- { title: 'Expertise', url: '/list/e/1' },
- ],
- selectedOrder: 'Popularity',
- }))
- .trait('single order', {
- orders: [{ title: 'Popularity', url: '/list/p/1' }],
- });
-
-export default factory.package();
diff --git a/src/typedefs/proptypes/index.js b/src/typedefs/proptypes/index.js
index be87510ea..abc061b0f 100644
--- a/src/typedefs/proptypes/index.js
+++ b/src/typedefs/proptypes/index.js
@@ -5,7 +5,6 @@ import html from './html';
import language from './language';
import meta from './meta';
import paginator from './paginator';
-import sorter from './sorter';
import snippet from './snippet';
import tags from './tags';
import chip from './chip';
@@ -18,7 +17,6 @@ export default {
language,
meta,
paginator,
- sorter,
snippet,
tags,
chip,
diff --git a/src/typedefs/proptypes/paginator.js b/src/typedefs/proptypes/paginator.js
index f53d91103..66ecfebbd 100644
--- a/src/typedefs/proptypes/paginator.js
+++ b/src/typedefs/proptypes/paginator.js
@@ -4,5 +4,4 @@ export default shape({
pageNumber: number,
totalPages: number,
baseUrl: string,
- slugOrderingSegment: string,
});
diff --git a/src/typedefs/proptypes/sorter.js b/src/typedefs/proptypes/sorter.js
deleted file mode 100644
index 45ded0e5e..000000000
--- a/src/typedefs/proptypes/sorter.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { shape, string, arrayOf } from 'prop-types';
-
-export default shape({
- orders: arrayOf(
- shape({
- url: string,
- title: string,
- })
- ),
- selectedOrder: string,
-});
diff --git a/src/utils/array.js b/src/utils/array.js
index 9390ecb8f..f4268cc94 100644
--- a/src/utils/array.js
+++ b/src/utils/array.js
@@ -14,17 +14,6 @@ export const chunk = (arr, size) =>
*/
export const uniqueElements = arr => [...new Set(arr)];
-/**
- * Inserts an element at the given index of the array (mutative).
- * @param {number} i - The index in which to insert the element.
- * @param {*} v - Element to be inserted.
- * @param {array} arr - The array to be mutated.
- */
-export const insertAt = (i, v, arr) => {
- arr.splice(i + 1, 0, v);
- return arr;
-};
-
/**
* Gets a random element from an array.
* @param {array} arr - The array to be sampled.
diff --git a/src/utils/array.test.js b/src/utils/array.test.js
index 3c29d626e..b4860c886 100644
--- a/src/utils/array.test.js
+++ b/src/utils/array.test.js
@@ -1,4 +1,4 @@
-import { uniqueElements, insertAt, chunk, sample } from './array';
+import { uniqueElements, chunk, sample } from './array';
describe('uniqueElements', () => {
it('returns the unique elements in an array', () => {
@@ -15,13 +15,6 @@ describe('chunk', () => {
});
});
-describe('insertAt', () => {
- it('inserts the element at the given index', () => {
- let arr = [1, 2, 3];
- expect(insertAt(1, 4, arr)).toEqual([1, 2, 4, 3]);
- });
-});
-
describe('sample', () => {
it('returns a random element from the given array', () => {
let arr = [1, 2, 3];
diff --git a/src/utils/index.js b/src/utils/index.js
index a76ae7de6..339ce59c2 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -8,39 +8,28 @@ import {
optimizeNodes,
optimizeAllNodes,
getURLParameters,
- getRootURL,
- getBaseURL,
truncateString,
} from './string';
-import combineClassNames from '@chalarangelo/combine-class-names';
-
-import { uniqueElements, insertAt, chunk, sample, shuffle } from './array';
+import { uniqueElements, chunk, sample, shuffle } from './array';
import { throttle } from './function';
-import { generateStructuredData, hasKeys, hasKey, get } from './object';
+import { generateStructuredData } from './object';
export {
capitalize,
toKebabCase,
convertToSeoSlug,
addTrailingSlashToSlug,
- combineClassNames,
escapeHTML,
stripMarkdownFormat,
optimizeNodes,
optimizeAllNodes,
getURLParameters,
- getBaseURL,
- getRootURL,
throttle,
generateStructuredData,
- hasKeys,
- hasKey,
- get,
uniqueElements,
- insertAt,
chunk,
sample,
truncateString,
diff --git a/src/utils/object.js b/src/utils/object.js
index 8700dbb4f..263751790 100644
--- a/src/utils/object.js
+++ b/src/utils/object.js
@@ -1,45 +1,3 @@
-/* eslint-disable no-prototype-builtins */
-/**
- * Check if an object has the given key.
- * @param {object} obj - An object.
- * @param {array} keys - A list of nested keys.
- */
-export const hasKey = (obj, keys) => {
- return (
- keys.length > 0 &&
- keys.every(key => {
- if (typeof obj !== 'object' || !obj.hasOwnProperty(key)) return false;
- obj = obj[key];
- return true;
- })
- );
-};
-
-/**
- * Check if an object has all the given keys.
- * @param {object} obj - A plain object.
- * @param {array} keys - An array of stringified keys.
- */
-export const hasKeys = (obj, keys) =>
- typeof obj === 'object' &&
- keys.every(key => hasKey(obj, Array.isArray(key) ? key : [key]));
-
-/**
- * Retrieve a set of properties indicated by the given selectors from an object.
- * @param {object} from - An object.
- * @param {array} selectors - A list of selector keys.
- */
-export const get = (from, selectors) =>
- selectors
- .map(s => (Array.isArray(s) ? s.join('.') : s))
- .map(s =>
- s
- .replace(/\[([^[\]]*)\]/g, '.$1.')
- .split('.')
- .filter(t => t !== '')
- .reduce((prev, cur) => prev && prev[cur], from)
- );
-
/**
* Generates structured data for a given entity based on the type.
* @param {object} structuredData - An object with the required information.
diff --git a/src/utils/object.test.js b/src/utils/object.test.js
index aed9932f2..6183c5045 100644
--- a/src/utils/object.test.js
+++ b/src/utils/object.test.js
@@ -1,47 +1,10 @@
-import { generateStructuredData, hasKey, hasKeys, get } from './object';
+import { generateStructuredData } from './object';
import {
listingStructuredData,
snippetStructuredData,
} from 'test/fixtures/metadata';
-describe('hasKey', () => {
- it('returns the correct result for a regular key', () => {
- expect(hasKey({ a: 'yes' }, ['a'])).toEqual(true);
- });
- it('returns the correct result for a regular key', () => {
- expect(hasKey({ a: 'yes' }, ['b'])).toEqual(false);
- });
-
- it('returns the correct result for nested keys', () => {
- expect(hasKey({ a: { b: { c: 'yes' } } }, ['a', 'b', 'c'])).toEqual(true);
- });
-
- it('returns the correct result for non-objects', () => {
- expect(hasKey('nope', ['a'])).toEqual(false);
- });
-});
-
-describe('hasKeys', () => {
- it('returns the correct result for the given keys', () => {
- expect(
- hasKeys({ a: { b: { c: 'yes' }, d: 1 }, e: true }, ['e', ['a', 'b'], 'a'])
- ).toEqual(true);
- });
-});
-
-describe('get', () => {
- it('returns the correct result for the given keys', () => {
- expect(
- get({ a: { b: { c: 'yes' }, d: 1 }, e: true }, [
- 'e',
- ['a', 'b', 'c'],
- ['a', 'd'],
- ])
- ).toEqual([true, 'yes', 1]);
- });
-});
-
describe('generateStructuredData', () => {
describe('with a snippet', () => {
let result;
diff --git a/src/utils/string.js b/src/utils/string.js
index 48ae0b0c3..34ed25b7f 100644
--- a/src/utils/string.js
+++ b/src/utils/string.js
@@ -63,19 +63,6 @@ export const getURLParameters = url =>
{}
);
-/**
- * Returns the URL without any parameters.
- * @param {string} url - The URL to be parsed.
- */
-export const getBaseURL = url =>
- url.indexOf('?') > 0 ? url.slice(0, url.indexOf('?')) : url;
-
-/**
- * Returns the root URL without any parameters..
- * @param {string} url - The URL to be parsed.
- */
-export const getRootURL = url => url.split('/').slice(0, 3).join('/');
-
/**
* Strips markdown format from a string.
* @param {string} str - The markdown string to be stripped.
diff --git a/src/utils/string.test.js b/src/utils/string.test.js
index 6d7abe26a..1fb300781 100644
--- a/src/utils/string.test.js
+++ b/src/utils/string.test.js
@@ -3,7 +3,6 @@ import {
optimizeNodes,
optimizeAllNodes,
getURLParameters,
- getBaseURL,
escapeHTML,
stripMarkdownFormat,
toKebabCase,
@@ -55,14 +54,6 @@ describe('getURLParameters', () => {
});
});
-describe('getBaseURL', () => {
- it('returns the current URL without parameters', () => {
- expect(getBaseURL('http://url.com/page?name=Adam&surname=Smith')).toBe(
- 'http://url.com/page'
- );
- });
-});
-
describe('stripMarkdownFormat', () => {
it('strips down markdown format', () => {
const md = 'I have `code` and [links](lala). \nI am also multiline.';