rebase on oct-10-2023

This commit is contained in:
Rachit Bhargava
2023-10-10 17:23:21 -04:00
parent d37566ffb6
commit d096058d7d
4789 changed files with 254611 additions and 307223 deletions

View File

@@ -6,7 +6,7 @@ import {
AttributeQuery,
AttributeTerm,
} from '@woocommerce/types';
import { sortBy } from 'lodash';
import { sort } from 'fast-sort';
/**
* Given a query object, removes an attribute filter by a single slug.
@@ -51,7 +51,7 @@ export const removeAttributeFilterBySlug = (
returnQuery.push( currentQuery );
}
setQuery( sortBy( returnQuery, 'attribute' ) );
setQuery( sort( returnQuery ).asc( 'attribute' ) );
};
/**
@@ -88,7 +88,7 @@ export const updateAttributeFilter = (
operator,
slug: attributeTerms.map( ( { slug } ) => slug ).sort(),
} );
setQuery( sortBy( returnQuery, 'attribute' ) );
setQuery( sort( returnQuery ).asc( 'attribute' ) );
}
return returnQuery;

View File

@@ -6,7 +6,7 @@ import { getSettingWithCoercion } from '@woocommerce/settings';
import { isBoolean } from '@woocommerce/types';
const filteringForPhpTemplate = getSettingWithCoercion(
'is_rendering_php_template',
'isRenderingPhpTemplate',
false,
isBoolean
);
@@ -34,6 +34,34 @@ export function getUrlParameter( name: string ) {
*/
export function changeUrl( newUrl: string ) {
if ( filteringForPhpTemplate ) {
/**
* We want to remove page number from URL whenever filters are changed.
* This will move the user to the first page of results.
*
* There are following page number formats:
* 1. query-{number}-page={number} (ex. query-1-page=2)
* - ref: https://github.com/WordPress/gutenberg/blob/5693a62214b6c76d3dc5f3f69d8aad187748af79/packages/block-library/src/query-pagination-numbers/index.php#L18
* 2. query-page={number} (ex. query-page=2)
* - ref: same as above
* 3. page/{number} (ex. page/2) (Default WordPress pagination format)
*/
newUrl = newUrl.replace(
/(?:query-(?:\d+-)?page=(\d+))|(?:page\/(\d+))/g,
''
);
/**
* If the URL ends with '?', we remove the trailing '?' from the URL.
* The trailing '?' in a URL is unnecessary and can cause the page to
* reload, which can negatively affect performance. By removing the '?',
* we prevent this unnecessary reload. This is safe to do even if there
* are query parameters, as they will not be affected by the removal
* of a trailing '?'.
*/
if ( newUrl.endsWith( '?' ) ) {
newUrl = newUrl.slice( 0, -1 );
}
window.location.href = newUrl;
} else {
window.history.replaceState( {}, '', newUrl );

View File

@@ -3,7 +3,10 @@ export * from './attributes-query';
export * from './attributes';
export * from './filters';
export * from './notices';
export * from './object-operations';
export * from './products';
export * from './shared-attributes';
export * from './useThrottle';
export * from './sanitize-html';
export * from './is-site-editor-page';
export * from './is-widget-editor-page';
export * from './trim-words';

View File

@@ -0,0 +1,21 @@
/**
* Internal dependencies
*/
import { isObject } from '../types/type-guards';
export const isSiteEditorPage = ( store: unknown ): boolean => {
if ( isObject( store ) ) {
const editedPostType = (
store as {
getEditedPostType: () => string;
}
).getEditedPostType();
return (
editedPostType === 'wp_template' ||
editedPostType === 'wp_template_part'
);
}
return false;
};

View File

@@ -0,0 +1,18 @@
/**
* Internal dependencies
*/
import { isObject } from '../types/type-guards';
export const isWidgetEditorPage = ( store: unknown ): boolean => {
if ( isObject( store ) ) {
const widgetAreas = (
store as {
getWidgetAreas: () => string;
}
).getWidgetAreas();
return Array.isArray( widgetAreas ) && widgetAreas.length > 0;
}
return false;
};

View File

@@ -0,0 +1,8 @@
/**
* Returns an object without a key.
*/
export function objectOmit< T, K extends keyof T >( obj: T, key: K ) {
const { [ key ]: omit, ...rest } = obj;
return rest;
}

View File

@@ -17,7 +17,7 @@ export default {
*/
columns: {
type: 'number',
default: getSetting( 'default_columns', 3 ),
default: getSetting( 'defaultColumns', 3 ),
},
/**
@@ -25,7 +25,7 @@ export default {
*/
rows: {
type: 'number',
default: getSetting( 'default_rows', 3 ),
default: getSetting( 'defaultRows', 3 ),
},
/**

View File

@@ -0,0 +1,91 @@
/**
* External dependencies
*/
import {
appendMoreText,
removeTags,
trimCharacters,
trimWords,
} from '@woocommerce/utils';
describe( 'trim-words', () => {
describe( 'removeTags', () => {
it( 'Removes HTML tags from a string', () => {
const string = '<div><a href="/index.php">trim-words.ts</a></div>';
const trimmedString = removeTags( string );
expect( trimmedString ).toEqual( 'trim-words.ts' );
} );
} );
describe( 'appendMoreText', () => {
it( 'Removes trailing punctuation and appends some characters to a string', () => {
const string = 'trim-words.ts,';
const appendedString = appendMoreText( string, '...' );
expect( appendedString ).toEqual( 'trim-words.ts...' );
} );
} );
describe( 'trimWords', () => {
const testContent =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.';
it( 'Limits words in string and returns trimmed version', () => {
const trimmedString = trimWords( testContent, 3 );
expect( trimmedString ).toBe(
'<p>Lorem ipsum dolor&hellip;</p>\n'
);
} );
it( 'Limits words in string and returns trimmed version with custom moreText', () => {
const trimmedString = trimWords( testContent, 4, '... read more.' );
expect( trimmedString ).toEqual(
'<p>Lorem ipsum dolor sit... read more.</p>\n'
);
} );
it( 'Limits words in string and returns trimmed version without autop', () => {
const trimmedString = trimWords(
testContent,
3,
'&hellip;',
false
);
expect( trimmedString ).toEqual( 'Lorem ipsum dolor&hellip;' );
} );
it( 'does not append anything if the text is shorter than the trim limit', () => {
const trimmedString = trimWords( testContent, 100 );
expect( trimmedString ).toEqual( '<p>' + testContent + '</p>\n' );
} );
} );
describe( 'trimCharacters', () => {
const testContent = 'Lorem ipsum dolor sit amet.';
it( 'Limits characters in string and returns trimmed version including spaces', () => {
const result = trimCharacters( testContent, 10 );
expect( result ).toEqual( '<p>Lorem ipsu&hellip;</p>\n' );
} );
it( 'Limits characters in string and returns trimmed version excluding spaces', () => {
const result = trimCharacters( testContent, 10, false );
expect( result ).toEqual( '<p>Lorem ipsum&hellip;</p>\n' );
} );
it( 'Limits characters in string and returns trimmed version with custom moreText', () => {
const result = trimCharacters(
testContent,
10,
false,
'... read more.'
);
expect( result ).toEqual( '<p>Lorem ipsum... read more.</p>\n' );
} );
it( 'Limits characters in string and returns trimmed version without autop', () => {
const result = trimCharacters(
testContent,
10,
false,
'... read more.',
false
);
expect( result ).toEqual( 'Lorem ipsum... read more.' );
} );
it( 'does not append anything if the text is shorter than the trim limit', () => {
const trimmedString = trimCharacters( testContent, 1000 );
expect( trimmedString ).toEqual( '<p>' + testContent + '</p>\n' );
} );
} );
} );

View File

@@ -0,0 +1,100 @@
/**
* External dependencies
*/
import { autop } from '@wordpress/autop';
/**
* Remove HTML tags from a string.
*
* @param {string} htmlString String to remove tags from.
* @return {string} Plain text string.
*/
export const removeTags = ( htmlString: string ) => {
const tagsRegExp = /<\/?[a-z][^>]*?>/gi;
return htmlString.replace( tagsRegExp, '' );
};
/**
* Remove trailing punctuation and append some characters to a string.
*
* @param {string} text Text to append to.
* @param {string} moreText Text to append.
* @return {string} String with appended characters.
*/
export const appendMoreText = ( text: string, moreText: string ) => {
return text.replace( /[\s|\.\,]+$/i, '' ) + moreText;
};
/**
* Limit words in string and returned trimmed version.
*
* @param {string} text Text to trim.
* @param {number} maxLength Number of countType to limit to.
* @param {string} moreText Appended to the trimmed string.
* @param {string} useAutop Whether to format with autop before returning.
* @return {string} Trimmed string.
*/
export const trimWords = (
text: string,
maxLength: number,
moreText = '&hellip;',
useAutop = true
) => {
const textToTrim = removeTags( text );
const trimmedText = textToTrim
.split( ' ' )
.splice( 0, maxLength )
.join( ' ' );
if ( trimmedText === textToTrim ) {
return useAutop ? autop( textToTrim ) : textToTrim;
}
if ( ! useAutop ) {
return appendMoreText( trimmedText, moreText );
}
return autop( appendMoreText( trimmedText, moreText ) );
};
/**
* Limit characters in string and returned trimmed version.
*
* @param {string} text Text to trim.
* @param {number} maxLength Number of countType to limit to.
* @param {boolean} includeSpaces Should spaces be included in the count.
* @param {string} moreText Appended to the trimmed string.
* @param {string} useAutop Whether to format with autop before returning.
* @return {string} Trimmed string.
*/
export const trimCharacters = (
text: string,
maxLength: number,
includeSpaces = true,
moreText = '&hellip;',
useAutop = true
) => {
const textToTrim = removeTags( text );
const trimmedText = textToTrim.slice( 0, maxLength );
if ( trimmedText === textToTrim ) {
return useAutop ? autop( textToTrim ) : textToTrim;
}
if ( includeSpaces ) {
return autop( appendMoreText( trimmedText, moreText ) );
}
const matchSpaces = trimmedText.match( /([\s]+)/g );
const spaceCount = matchSpaces ? matchSpaces.length : 0;
const trimmedTextExcludingSpaces = textToTrim.slice(
0,
maxLength + spaceCount
);
if ( ! useAutop ) {
return appendMoreText( trimmedTextExcludingSpaces, moreText );
}
return autop( appendMoreText( trimmedTextExcludingSpaces, moreText ) );
};

View File

@@ -1,34 +0,0 @@
/* eslint-disable you-dont-need-lodash-underscore/throttle */
/**
* External dependencies
*/
import { DebouncedFunc, throttle, ThrottleSettings } from 'lodash';
import { useCallback, useEffect, useRef } from '@wordpress/element';
/**
* Throttles a function inside a React functional component
*/
// Disabling this as lodash expects this and I didn't make using `unknown`
// work in practice.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useThrottle< T extends ( ...args: any[] ) => any >(
cb: T,
delay: number,
options?: ThrottleSettings
): DebouncedFunc< T > {
const cbRef = useRef( cb );
useEffect( () => {
cbRef.current = cb;
} );
// Disabling because we can't pass an arrow function in this case
// eslint-disable-next-line react-hooks/exhaustive-deps
const throttledCb = useCallback(
throttle( ( ...args ) => cbRef.current( ...args ), delay, options ),
[ delay ]
);
return throttledCb;
}