| @@ -1,21 +1,39 @@ | ||
| 1 | +import { _x } from '@wordpress/i18n' | |
| 2 | + | |
| 3 | +const DEFAULT_MAX_CHARS = 150 | |
| 4 | + | |
| 1 | 5 | export const toCamelCase = (text: string): string => |
| 2 | 6 | text.replace(/-(?<letter>[a-z])/g, (_, letter: string) => letter.toUpperCase()) |
| 3 | 7 | |
| 4 | -export const trimLeadingChar = (text: string, character: string): string => | |
| 5 | - character === text.charAt(0) ? text.slice(1) : text | |
| 8 | +export const trimLeadingChar = (text: string, characters: string): string => | |
| 9 | + characters.includes(text.charAt(0)) ? text.slice(1) : text | |
| 6 | 10 | |
| 7 | -export const trimTrailingChar = (text: string, character: string): string => | |
| 8 | - character === text.charAt(text.length - 1) ? text.slice(0, -1) : text | |
| 11 | +export const trimTrailingChar = (text: string, characters: string): string => | |
| 12 | + characters.includes(text.charAt(text.length - 1)) ? text.slice(0, -1) : text | |
| 9 | 13 | |
| 14 | +export const truncateChars = (text: string, chars = DEFAULT_MAX_CHARS): string => | |
| 15 | + text.length > chars | |
| 16 | + ? `${text.slice(0, chars)}${_x('…', 'truncated text', 'code-snippets')}` | |
| 17 | + : text | |
| 18 | + | |
| 10 | 19 | export const truncateWords = (text: string, wordCount: number): string => { |
| 11 | 20 | const words = text.trim().split(/\s+/) |
| 12 | 21 | |
| 13 | 22 | return words.length > wordCount |
| 14 | - ? `${words.slice(0, wordCount).join(' ')}…` | |
| 23 | + ? `${words.slice(0, wordCount).join(' ')}${_x('…', 'truncated text', 'code-snippets')}` | |
| 15 | 24 | : text |
| 16 | 25 | } |
| 17 | 26 | |
| 18 | -export const stripTags = (text: string): string => | |
| 19 | - text | |
| 20 | - .replace(/<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi, '') | |
| 21 | - .replace(/<\/?[a-z][a-z0-9]*\b[^>]*>/gi, '') | |
| 27 | +export const stripTags = (text: string): string => { | |
| 28 | + const document = new DOMParser().parseFromString(text, 'text/html') | |
| 29 | + const blockSelector = 'p,div,li,br,h1,h2,h3,h4,h5,h6,tr,td,th,ul,ol,blockquote,table,pre,hr,' + | |
| 30 | + 'dl,dt,dd,section,article,header,footer,figure,figcaption,' + | |
| 31 | + 'address,aside,nav,main,fieldset,form,details,summary,dialog,hgroup,caption' | |
| 32 | + | |
| 33 | + document.body.querySelectorAll('script,style').forEach(element => element.remove()) | |
| 34 | + document.body | |
| 35 | + .querySelectorAll(blockSelector) | |
| 36 | + .forEach(element => element.after(document.createTextNode(' '))) | |
| 37 | + | |
| 38 | + return (document.body.textContent ?? '').replace(/\s+/g, ' ').trim() | |
| 39 | +} | |