Merge branch 'main' into truncate-text

This commit is contained in:
Ibrahima G. Coulibaly
2025-03-11 18:30:49 +00:00
committed by GitHub
109 changed files with 6154 additions and 1880 deletions

View File

@@ -1,11 +1,113 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { GetGroupsType } from '@components/options/ToolOptions';
import { createPalindromeList } from './service';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function CreatePalindrome() {
return <Box>Lorem ipsum</Box>;
const initialValues = {
lastChar: true,
multiLine: false
};
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Create Simple Palindrome',
description:
'Creates a palindrome by repeating the text in reverse order, including the last character.',
sampleText: 'level',
sampleResult: 'levellevel',
sampleOptions: {
...initialValues,
lastChar: true
}
},
{
title: 'Create Palindrome Without Last Character Duplication',
description:
'Creates a palindrome without repeating the last character in the reverse part.',
sampleText: 'radar',
sampleResult: 'radarada',
sampleOptions: {
...initialValues,
lastChar: false
}
},
{
title: 'Multi-line Palindrome Creation',
description: 'Creates palindromes for each line independently.',
sampleText: 'mom\ndad\nwow',
sampleResult: 'mommom\ndaddad\nwowwow',
sampleOptions: {
...initialValues,
lastChar: true,
multiLine: true
}
}
];
export default function CreatePalindrome({
title,
longDescription
}: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
optionsValues: typeof initialValues,
input: string
) => {
const { lastChar, multiLine } = optionsValues;
setResult(createPalindromeList(input, lastChar, multiLine));
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Palindrome options',
component: [
<CheckboxWithDesc
key="lastChar"
checked={values.lastChar}
title="Include last character"
description="Repeat the last character in the reversed part"
onChange={(val) => updateField('lastChar', val)}
/>,
<CheckboxWithDesc
key="multiLine"
checked={values.multiLine}
title="Process multi-line text"
description="Create palindromes for each line independently"
onChange={(val) => updateField('multiLine', val)}
/>
]
}
];
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={getGroups}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input text'} value={input} onChange={setInput} />
}
resultComponent={
<ToolTextResult title={'Palindrome text'} value={result} />
}
toolInfo={{
title: 'What Is a String Palindrome Creator?',
description: longDescription
}}
exampleCards={exampleCards}
/>
);
}

View File

@@ -5,9 +5,12 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
name: 'Create palindrome',
path: 'create-palindrome',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:repeat',
description:
"World's simplest browser-based utility for creating palindromes from any text. Input text and instantly transform it into a palindrome that reads the same forward and backward. Perfect for word games, creating symmetrical text patterns, or exploring linguistic curiosities.",
shortDescription: 'Create text that reads the same forward and backward',
longDescription:
'This tool creates a palindrome from the given string. It does it by generating a copy of the string, reversing it, and appending it at the end of the original string. This method creates a palindrome with the last character duplicated twice. There is also another way to do it, which deletes the first letter of the reversed copy. In this case, when the string and the copy are joined together, you also get a palindrome but without the repeating last character. You can compare the two types of palindromes by switching between them in the options. You can also enable the multi-line mode that will create palindromes of every string on every line. Stringabulous!',
keywords: ['create', 'palindrome'],
component: lazy(() => import('./index'))
});

View File

@@ -1,11 +1,142 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { GetGroupsType } from '@components/options/ToolOptions';
import { extractSubstring } from './service';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function ExtractSubstring() {
return <Box>Lorem ipsum</Box>;
const initialValues = {
start: '1',
length: '5',
multiLine: false,
reverse: false
};
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Extract First 5 Characters',
description: 'This example extracts the first 5 characters from the text.',
sampleText: 'The quick brown fox jumps over the lazy dog.',
sampleResult: 'The q',
sampleOptions: {
...initialValues,
start: '1',
length: '5'
}
},
{
title: 'Extract Words from the Middle',
description:
'Extract a substring starting from position 11 with a length of 10 characters.',
sampleText: 'The quick brown fox jumps over the lazy dog.',
sampleResult: 'brown fox',
sampleOptions: {
...initialValues,
start: '11',
length: '10'
}
},
{
title: 'Multi-line Extraction with Reversal',
description: 'Extract characters 1-3 from each line and reverse them.',
sampleText: 'First line\nSecond line\nThird line',
sampleResult: 'riF\nceS\nihT',
sampleOptions: {
...initialValues,
start: '1',
length: '3',
multiLine: true,
reverse: true
}
}
];
export default function ExtractSubstring({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
optionsValues: typeof initialValues,
input: string
) => {
const { start, length, multiLine, reverse } = optionsValues;
try {
setResult(
extractSubstring(
input,
parseInt(start, 10),
parseInt(length, 10),
multiLine,
reverse
)
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
} else {
setResult('An unknown error occurred');
}
}
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Extraction options',
component: [
<TextFieldWithDesc
key="start"
value={values.start}
onOwnChange={(value) => updateField('start', value)}
description="Start position (1-based index)"
type="number"
/>,
<TextFieldWithDesc
key="length"
value={values.length}
onOwnChange={(value) => updateField('length', value)}
description="Number of characters to extract"
type="number"
/>,
<CheckboxWithDesc
key="multiLine"
checked={values.multiLine}
title="Process multi-line text"
description="Extract from each line independently"
onChange={(val) => updateField('multiLine', val)}
/>,
<CheckboxWithDesc
key="reverse"
checked={values.reverse}
title="Reverse output"
description="Reverse the extracted substring"
onChange={(val) => updateField('reverse', val)}
/>
]
}
];
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={getGroups}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input text'} value={input} onChange={setInput} />
}
resultComponent={
<ToolTextResult title={'Extracted text'} value={result} />
}
exampleCards={exampleCards}
/>
);
}

View File

@@ -5,9 +5,10 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
name: 'Extract substring',
path: 'extract-substring',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:content-cut',
description:
"World's simplest browser-based utility for extracting substrings from text. Easily extract specific portions of text by specifying start position and length. Perfect for parsing data, isolating specific parts of text, or data extraction tasks. Supports multi-line text processing and character-level precision.",
shortDescription: 'Extract specific portions of text by position and length',
keywords: ['extract', 'substring'],
component: lazy(() => import('./index'))
});

View File

@@ -22,11 +22,14 @@ export const stringTools = [
stringToMorse,
stringReplace,
stringRepeat,
stringTruncate
// stringReverse,
// stringRandomizeCase,
// stringUppercase,
// stringExtractSubstring,
// stringCreatePalindrome,
// stringPalindrome
stringTruncate,
stringReverse,
stringRandomizeCase,
stringUppercase,
stringExtractSubstring,
stringCreatePalindrome,
stringPalindrome,
stringQuote,
stringRotate,
stringRot13
];

View File

@@ -1,20 +1,13 @@
import { Box } from '@mui/material';
import React, { useRef, useState } from 'react';
import React, { useState } from 'react';
import * as Yup from 'yup';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
import ToolContent from '@components/ToolContent';
import { GetGroupsType } from '@components/options/ToolOptions';
import { mergeText } from './service';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
import ToolInfo from '@components/ToolInfo';
import Separator from '@components/Separator';
import ToolExamples, {
CardExampleType
} from '@components/examples/ToolExamples';
import { FormikProps } from 'formik';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
const initialValues = {
@@ -116,7 +109,6 @@ s
export default function JoinText({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const formRef = useRef<FormikProps<InitialValuesType>>(null);
const compute = (optionsValues: InitialValuesType, input: any) => {
const { joinCharacter, deleteBlank, deleteTrailing } = optionsValues;
setResult(mergeText(input, deleteBlank, deleteTrailing, joinCharacter));
@@ -151,36 +143,27 @@ export default function JoinText({ title }: ToolComponentProps) {
}
];
return (
<Box>
<ToolInputAndResult
input={
<ToolTextInput
title={'Text Pieces'}
value={input}
onChange={setInput}
/>
}
result={<ToolTextResult title={'Joined Text'} value={result} />}
/>
<ToolOptions
formRef={formRef}
compute={compute}
getGroups={getGroups}
initialValues={initialValues}
input={input}
/>
<ToolInfo
title="What Is a Text Joiner?"
description="With this tool you can join parts of the text together. It takes a list of text values, separated by newlines, and merges them together. You can set the character that will be placed between the parts of the combined text. Also, you can ignore all empty lines and remove spaces and tabs at the end of all lines. Textabulous!"
/>
<Separator backgroundColor="#5581b5" margin="50px" />
<ToolExamples
title={title}
exampleCards={exampleCards}
getGroups={getGroups}
formRef={formRef}
setInput={setInput}
/>
</Box>
<ToolContent
title={title}
initialValues={initialValues}
compute={compute}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput
title={'Text Pieces'}
value={input}
onChange={setInput}
/>
}
resultComponent={<ToolTextResult title={'Joined Text'} value={result} />}
getGroups={getGroups}
toolInfo={{
title: 'What Is a Text Joiner?',
description:
'With this tool you can join parts of the text together. It takes a list of text values, separated by newlines, and merges them together. You can set the character that will be placed between the parts of the combined text. Also, you can ignore all empty lines and remove spaces and tabs at the end of all lines. Textabulous!'
}}
exampleCards={exampleCards}
/>
);
}

View File

@@ -1,11 +1,126 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState, useRef } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
import { palindromeList, SplitOperatorType } from './service';
import RadioWithTextField from '@components/options/RadioWithTextField';
import ToolInputAndResult from '@components/ToolInputAndResult';
import ToolExamples, {
CardExampleType
} from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { FormikProps } from 'formik';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Palindrome() {
return <Box>Lorem ipsum</Box>;
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
symbolValue: ' ',
regexValue: '\\s+'
};
const splitOperators: {
title: string;
description: string;
type: SplitOperatorType;
}[] = [
{
title: 'Use a Symbol for Splitting',
description:
'Character that will be used to split text into parts for palindrome checking.',
type: 'symbol'
},
{
title: 'Use a Regex for Splitting',
type: 'regex',
description:
'Regular expression that will be used to split text into parts for palindrome checking.'
}
];
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Check for Word Palindromes',
description:
'Checks if each word in the text is a palindrome. Returns "true" for palindromes and "false" for non-palindromes.',
sampleText: 'radar level hello anna',
sampleResult: 'true true false true',
sampleOptions: {
...initialValues,
symbolValue: ' '
}
},
{
title: 'Check CSV Words',
description: 'Checks palindrome status for comma-separated words.',
sampleText: 'mom,dad,wow,test',
sampleResult: 'true true true false',
sampleOptions: {
...initialValues,
symbolValue: ','
}
},
{
title: 'Check with Regular Expression',
description:
'Use a regular expression to split text and check for palindromes.',
sampleText: 'level:madam;noon|test',
sampleResult: 'true true true false',
sampleOptions: {
...initialValues,
splitOperatorType: 'regex',
regexValue: '[:|;]|\\|'
}
}
];
export default function Palindrome({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
optionsValues: typeof initialValues,
input: string
) => {
const { splitOperatorType, symbolValue, regexValue } = optionsValues;
const separator = splitOperatorType === 'symbol' ? symbolValue : regexValue;
setResult(palindromeList(splitOperatorType, input, separator));
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Splitting options',
component: splitOperators.map(({ title, description, type }) => (
<RadioWithTextField
key={type}
checked={type === values.splitOperatorType}
title={title}
fieldName={'splitOperatorType'}
description={description}
value={values[`${type}Value`]}
onRadioClick={() => updateField('splitOperatorType', type)}
onTextChange={(val) => updateField(`${type}Value`, val)}
/>
))
}
];
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={getGroups}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={
<ToolTextResult title={'Palindrome results'} value={result} />
}
exampleCards={exampleCards}
/>
);
}

View File

@@ -5,9 +5,10 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
name: 'Palindrome',
path: 'palindrome',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:search',
description:
"World's simplest browser-based utility for checking if text is a palindrome. Instantly verify if your text reads the same forward and backward. Perfect for word puzzles, linguistic analysis, or validating symmetrical text patterns. Supports various delimiters and multi-word palindrome detection.",
shortDescription: 'Check if text reads the same forward and backward',
keywords: ['palindrome'],
component: lazy(() => import('./index'))
});

View File

@@ -1,11 +1,149 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { stringQuoter } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Quote() {
return <Box>Lorem ipsum</Box>;
}
interface InitialValuesType {
leftQuote: string;
rightQuote: string;
doubleQuotation: boolean;
emptyQuoting: boolean;
multiLine: boolean;
}
const initialValues: InitialValuesType = {
leftQuote: '"',
rightQuote: '"',
doubleQuotation: false,
emptyQuoting: true,
multiLine: true
};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Quote text with double quotes',
description: 'This example shows how to quote text with double quotes.',
sampleText: 'Hello World',
sampleResult: '"Hello World"',
sampleOptions: {
leftQuote: '"',
rightQuote: '"',
doubleQuotation: false,
emptyQuoting: true,
multiLine: false
}
},
{
title: 'Quote multi-line text with single quotes',
description:
'This example shows how to quote multi-line text with single quotes.',
sampleText: 'Hello\nWorld',
sampleResult: "'Hello'\n'World'",
sampleOptions: {
leftQuote: "'",
rightQuote: "'",
doubleQuotation: false,
emptyQuoting: true,
multiLine: true
}
},
{
title: 'Quote with custom quotes',
description: 'This example shows how to quote text with custom quotes.',
sampleText: 'Hello World',
sampleResult: '<<Hello World>>',
sampleOptions: {
leftQuote: '<<',
rightQuote: '>>',
doubleQuotation: false,
emptyQuoting: true,
multiLine: false
}
}
];
export default function Quote({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
setResult(
stringQuoter(
input,
optionsValues.leftQuote,
optionsValues.rightQuote,
optionsValues.doubleQuotation,
optionsValues.emptyQuoting,
optionsValues.multiLine
)
);
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Quote Options',
component: (
<Box>
<TextFieldWithDesc
value={values.leftQuote}
onOwnChange={(val) => updateField('leftQuote', val)}
description={'Left quote character(s)'}
/>
<TextFieldWithDesc
value={values.rightQuote}
onOwnChange={(val) => updateField('rightQuote', val)}
description={'Right quote character(s)'}
/>
<CheckboxWithDesc
checked={values.doubleQuotation}
onChange={(checked) => updateField('doubleQuotation', checked)}
title={'Allow double quotation'}
/>
<CheckboxWithDesc
checked={values.emptyQuoting}
onChange={(checked) => updateField('emptyQuoting', checked)}
title={'Quote empty lines'}
/>
<CheckboxWithDesc
checked={values.multiLine}
onChange={(checked) => updateField('multiLine', checked)}
title={'Process as multi-line text'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input Text" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Quoted Text" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
toolInfo={{
title: 'Text Quoter',
description:
"This tool allows you to add quotes around text. You can choose different quote characters, handle multi-line text, and control how empty lines are processed. It's useful for preparing text for programming, formatting data, or creating stylized text."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -6,8 +6,9 @@ export const tool = defineTool('string', {
name: 'Quote',
path: 'quote',
icon: 'proicons:quote',
description: '',
shortDescription: '',
description:
'A tool to add quotation marks or custom characters around text. Perfect for formatting strings for code, citations, or stylistic purposes.',
shortDescription: 'Add quotes around text easily.',
keywords: ['quote'],
component: lazy(() => import('./index'))
});

View File

@@ -1,11 +1,66 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { randomizeCase } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function RandomizeCase() {
return <Box>Lorem ipsum</Box>;
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Randomize Text Case',
description:
'This example turns normal text into a random mix of uppercase and lowercase letters.',
sampleText: 'The quick brown fox jumps over the lazy dog.',
sampleResult: 'tHe qUIcK BrOWn fOx JuMPs ovEr ThE LaZy Dog.',
sampleOptions: {}
},
{
title: 'Randomize Code Case',
description:
'Transform code identifiers with randomized case for a chaotic look.',
sampleText:
'function calculateTotal(price, quantity) { return price * quantity; }',
sampleResult:
'FuNcTIon cAlCuLAtEtOtaL(pRicE, qUaNTiTy) { rETuRn PrICe * QuAnTiTY; }',
sampleOptions: {}
},
{
title: 'Randomize a Famous Quote',
description:
'Give a unique randomized case treatment to a well-known quote.',
sampleText: 'To be or not to be, that is the question.',
sampleResult: 'tO Be oR NoT To bE, ThAt iS ThE QueStIoN.',
sampleOptions: {}
}
];
export default function RandomizeCase({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
_optionsValues: typeof initialValues,
input: string
) => {
setResult(randomizeCase(input));
};
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={null}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={
<ToolTextResult title={'Randomized text'} value={result} />
}
exampleCards={exampleCards}
/>
);
}

View File

@@ -5,9 +5,10 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
name: 'Randomize case',
path: 'randomize-case',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:format-textdirection-l-to-r',
description:
"World's simplest browser-based utility for randomizing the case of text. Just paste your text and get it instantly transformed with random uppercase and lowercase letters. Perfect for creating playful text styles, meme text, or simulating chaotic writing.",
shortDescription: 'Convert text to random uppercase and lowercase letters',
keywords: ['randomize', 'case'],
component: lazy(() => import('./index'))
});

View File

@@ -2,10 +2,8 @@ import { Box } from '@mui/material';
import React, { useRef, useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
import ToolExamples, {
CardExampleType
} from '@components/examples/ToolExamples';
@@ -16,6 +14,7 @@ import removeDuplicateLines, {
DuplicateRemoverOptions,
NewlineOption
} from './service';
import ToolContent from '@components/ToolContent';
// Initial values for our form
const initialValues: DuplicateRemoverOptions = {
@@ -174,7 +173,6 @@ Elderberry`,
export default function RemoveDuplicateLines({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const formRef = useRef<FormikProps<typeof initialValues>>(null);
const computeExternal = (
optionsValues: typeof initialValues,
@@ -183,78 +181,65 @@ export default function RemoveDuplicateLines({ title }: ToolComponentProps) {
setResult(removeDuplicateLines(inputText, optionsValues));
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Operation Mode',
component: operationModes.map(({ title, description, value }) => (
<SimpleRadio
key={value}
checked={value === values.mode}
title={title}
description={description}
onClick={() => updateField('mode', value)}
/>
))
},
{
title: 'Newlines, Tabs and Spaces',
component: [
...newlineOptions.map(({ title, description, value }) => (
<SimpleRadio
key={value}
checked={value === values.newlines}
title={title}
description={description}
onClick={() => updateField('newlines', value)}
/>
)),
<CheckboxWithDesc
key="trimTextLines"
checked={values.trimTextLines}
title="Trim Text Lines"
description="Before filtering uniques, remove tabs and spaces from the beginning and end of all lines."
onChange={(checked) => updateField('trimTextLines', checked)}
/>
]
},
{
title: 'Sort Lines',
component: [
<CheckboxWithDesc
key="sortLines"
checked={values.sortLines}
title="Sort the Output Lines"
description="After removing the duplicates, sort the unique lines."
onChange={(checked) => updateField('sortLines', checked)}
/>
]
}
];
return (
<Box>
<ToolInputAndResult
input={<ToolTextInput value={input} onChange={setInput} />}
result={
<ToolTextResult title={'Text without duplicates'} value={result} />
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={
<ToolTextResult title={'Text without duplicates'} value={result} />
}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Operation Mode',
component: operationModes.map(({ title, description, value }) => (
<SimpleRadio
key={value}
checked={value === values.mode}
title={title}
description={description}
onClick={() => updateField('mode', value)}
/>
))
},
{
title: 'Newlines, Tabs and Spaces',
component: [
...newlineOptions.map(({ title, description, value }) => (
<SimpleRadio
key={value}
checked={value === values.newlines}
title={title}
description={description}
onClick={() => updateField('newlines', value)}
/>
)),
<CheckboxWithDesc
key="trimTextLines"
checked={values.trimTextLines}
title="Trim Text Lines"
description="Before filtering uniques, remove tabs and spaces from the beginning and end of all lines."
onChange={(checked) => updateField('trimTextLines', checked)}
/>
]
},
{
title: 'Sort Lines',
component: [
<CheckboxWithDesc
key="sortLines"
checked={values.sortLines}
title="Sort the Output Lines"
description="After removing the duplicates, sort the unique lines."
onChange={(checked) => updateField('sortLines', checked)}
/>
]
}
/>
<ToolOptions
compute={computeExternal}
getGroups={getGroups}
initialValues={initialValues}
input={input}
/>
<ToolExamples
title={title}
exampleCards={exampleCards}
getGroups={getGroups}
formRef={formRef}
setInput={setInput}
/>
</Box>
]}
compute={computeExternal}
setInput={setInput}
exampleCards={exampleCards}
/>
);
}

View File

@@ -1,11 +1,119 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState, useRef } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
import { stringReverser } from './service';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
import ToolExamples, {
CardExampleType
} from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { FormikProps } from 'formik';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Reverse() {
return <Box>Lorem ipsum</Box>;
const initialValues = {
multiLine: true,
emptyItems: false,
trim: false
};
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Simple Text Reversal',
description:
'Reverses each character in the text. Perfect for creating mirror text.',
sampleText: 'Hello World',
sampleResult: 'dlroW olleH',
sampleOptions: {
...initialValues,
multiLine: false
}
},
{
title: 'Multi-line Reversal',
description:
'Reverses each line independently while preserving the line breaks.',
sampleText: 'First line\nSecond line\nThird line',
sampleResult: 'enil tsriF\nenil dnoceS\nenil drihT',
sampleOptions: {
...initialValues,
multiLine: true
}
},
{
title: 'Clean Reversed Text',
description:
'Trims whitespace and skips empty lines before reversing the text.',
sampleText: ' Spaces removed \n\nEmpty line skipped',
sampleResult: 'devomer secapS\ndeppiks enil ytpmE',
sampleOptions: {
...initialValues,
multiLine: true,
emptyItems: true,
trim: true
}
}
];
export default function Reverse({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
optionsValues: typeof initialValues,
input: string
) => {
const { multiLine, emptyItems, trim } = optionsValues;
setResult(stringReverser(input, multiLine, emptyItems, trim));
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Reversal options',
component: [
<CheckboxWithDesc
key="multiLine"
checked={values.multiLine}
title="Process multi-line text"
description="Each line will be reversed independently"
onChange={(val) => updateField('multiLine', val)}
/>,
<CheckboxWithDesc
key="emptyItems"
checked={values.emptyItems}
title="Skip empty lines"
description="Empty lines will be removed from the output"
onChange={(val) => updateField('emptyItems', val)}
/>,
<CheckboxWithDesc
key="trim"
checked={values.trim}
title="Trim whitespace"
description="Remove leading and trailing whitespace from each line"
onChange={(val) => updateField('trim', val)}
/>
]
}
];
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={getGroups}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={
<ToolTextResult title={'Reversed text'} value={result} />
}
exampleCards={exampleCards}
/>
);
}

View File

@@ -1,13 +1,13 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('string', {
name: 'Reverse',
path: 'reverse',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:swap-horiz',
description:
"World's simplest browser-based utility for reversing text. Input any text and get it instantly reversed, character by character. Perfect for creating mirror text, analyzing palindromes, or playing with text patterns. Preserves spaces and special characters while reversing.",
shortDescription: 'Reverse any text character by character',
keywords: ['reverse'],
component: lazy(() => import('./index'))
});

View File

@@ -1,11 +1,60 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState } from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { rot13 } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Rot13() {
return <Box>Lorem ipsum</Box>;
}
type InitialValuesType = Record<string, never>;
const initialValues: InitialValuesType = {};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Encode a message with ROT13',
description:
'This example shows how to encode a simple message using ROT13 cipher.',
sampleText: 'Hello, World!',
sampleResult: 'Uryyb, Jbeyq!',
sampleOptions: {}
},
{
title: 'Decode a ROT13 message',
description:
'This example shows how to decode a message that was encoded with ROT13.',
sampleText: 'Uryyb, Jbeyq!',
sampleResult: 'Hello, World!',
sampleOptions: {}
}
];
export default function Rot13({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (_: InitialValuesType, input: string) => {
if (input) setResult(rot13(input));
};
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input Text" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="ROT13 Result" value={result} />}
initialValues={initialValues}
getGroups={null}
toolInfo={{
title: 'What Is ROT13?',
description:
'ROT13 (rotate by 13 places) is a simple letter substitution cipher that replaces a letter with the 13th letter after it in the alphabet. ROT13 is a special case of the Caesar cipher which was developed in ancient Rome. Because there are 26 letters in the English alphabet, ROT13 is its own inverse; that is, to undo ROT13, the same algorithm is applied, so the same action can be used for encoding and decoding.'
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -6,8 +6,9 @@ export const tool = defineTool('string', {
name: 'Rot13',
path: 'rot13',
icon: 'hugeicons:encrypt',
description: '',
shortDescription: '',
description:
'A simple tool to encode or decode text using the ROT13 cipher, which replaces each letter with the letter 13 positions after it in the alphabet.',
shortDescription: 'Encode or decode text using ROT13 cipher.',
keywords: ['rot13'],
component: lazy(() => import('./index'))
});

View File

@@ -1,11 +1,131 @@
import React, { useState } from 'react';
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { rotateString } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Rotate() {
return <Box>Lorem ipsum</Box>;
}
interface InitialValuesType {
step: string;
direction: 'left' | 'right';
multiLine: boolean;
}
const initialValues: InitialValuesType = {
step: '1',
direction: 'right',
multiLine: true
};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Rotate text to the right',
description:
'This example shows how to rotate text to the right by 2 positions.',
sampleText: 'abcdef',
sampleResult: 'efabcd',
sampleOptions: {
step: '2',
direction: 'right',
multiLine: false
}
},
{
title: 'Rotate text to the left',
description:
'This example shows how to rotate text to the left by 2 positions.',
sampleText: 'abcdef',
sampleResult: 'cdefab',
sampleOptions: {
step: '2',
direction: 'left',
multiLine: false
}
},
{
title: 'Rotate multi-line text',
description:
'This example shows how to rotate each line of a multi-line text.',
sampleText: 'abcdef\nghijkl',
sampleResult: 'fabcde\nlghijk',
sampleOptions: {
step: '1',
direction: 'right',
multiLine: true
}
}
];
export default function Rotate({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: InitialValuesType, input: string) => {
if (input) {
const step = parseInt(optionsValues.step, 10) || 1;
const isRight = optionsValues.direction === 'right';
setResult(rotateString(input, step, isRight, optionsValues.multiLine));
}
};
const getGroups: GetGroupsType<InitialValuesType> = ({
values,
updateField
}) => [
{
title: 'Rotation Options',
component: (
<Box>
<TextFieldWithDesc
value={values.step}
onOwnChange={(val) => updateField('step', val)}
description={'Number of positions to rotate'}
type="number"
/>
<SimpleRadio
onClick={() => updateField('direction', 'right')}
checked={values.direction === 'right'}
title={'Rotate Right'}
/>
<SimpleRadio
onClick={() => updateField('direction', 'left')}
checked={values.direction === 'left'}
title={'Rotate Left'}
/>
<CheckboxWithDesc
checked={values.multiLine}
onChange={(checked) => updateField('multiLine', checked)}
title={'Process as multi-line text (rotate each line separately)'}
/>
</Box>
)
}
];
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input Text" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Rotated Text" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
toolInfo={{
title: 'String Rotation',
description:
'This tool allows you to rotate characters in a string by a specified number of positions. You can rotate to the left or right, and process multi-line text by rotating each line separately. String rotation is useful for simple text transformations, creating patterns, or implementing basic encryption techniques.'
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -6,8 +6,9 @@ export const tool = defineTool('string', {
name: 'Rotate',
path: 'rotate',
icon: 'carbon:rotate',
description: '',
shortDescription: '',
description:
'A tool to rotate characters in a string by a specified number of positions. Shift characters left or right while maintaining their relative order.',
shortDescription: 'Shift characters in text by position.',
keywords: ['rotate'],
component: lazy(() => import('./index'))
});

View File

@@ -2,16 +2,15 @@ import { Box } from '@mui/material';
import React, { useRef, useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions, { GetGroupsType } from '@components/options/ToolOptions';
import { compute, SplitOperatorType } from './service';
import RadioWithTextField from '@components/options/RadioWithTextField';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
import ToolExamples, {
CardExampleType
} from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { FormikProps } from 'formik';
import ToolContent from '@components/ToolContent';
const initialValues = {
splitSeparatorType: 'symbol' as SplitOperatorType,
@@ -135,8 +134,11 @@ easy`,
export default function SplitText({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const formRef = useRef<FormikProps<typeof initialValues>>(null);
const computeExternal = (optionsValues: typeof initialValues, input: any) => {
const computeExternal = (
optionsValues: typeof initialValues,
input: string
) => {
const {
splitSeparatorType,
outputSeparator,
@@ -163,56 +165,44 @@ export default function SplitText({ title }: ToolComponentProps) {
);
};
const getGroups: GetGroupsType<typeof initialValues> = ({
values,
updateField
}) => [
{
title: 'Split separator options',
component: splitOperators.map(({ title, description, type }) => (
<RadioWithTextField
key={type}
checked={type === values.splitSeparatorType}
title={title}
fieldName={'splitSeparatorType'}
description={description}
value={values[`${type}Value`]}
onRadioClick={() => updateField('splitSeparatorType', type)}
onTextChange={(val) => updateField(`${type}Value`, val)}
/>
))
},
{
title: 'Output separator options',
component: outputOptions.map((option) => (
<TextFieldWithDesc
key={option.accessor}
value={values[option.accessor]}
onOwnChange={(value) => updateField(option.accessor, value)}
description={option.description}
/>
))
}
];
return (
<Box>
<ToolInputAndResult
input={<ToolTextInput value={input} onChange={setInput} />}
result={<ToolTextResult title={'Text pieces'} value={result} />}
/>
<ToolOptions
compute={computeExternal}
getGroups={getGroups}
initialValues={initialValues}
input={input}
/>
<ToolExamples
title={title}
exampleCards={exampleCards}
getGroups={getGroups}
formRef={formRef}
setInput={setInput}
/>
</Box>
<ToolContent
title={title}
input={input}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult title={'Text pieces'} value={result} />}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Split separator options',
component: splitOperators.map(({ title, description, type }) => (
<RadioWithTextField
key={type}
checked={type === values.splitSeparatorType}
title={title}
fieldName={'splitSeparatorType'}
description={description}
value={values[`${type}Value`]}
onRadioClick={() => updateField('splitSeparatorType', type)}
onTextChange={(val) => updateField(`${type}Value`, val)}
/>
))
},
{
title: 'Output separator options',
component: outputOptions.map((option) => (
<TextFieldWithDesc
key={option.accessor}
value={values[option.accessor]}
onOwnChange={(value) => updateField(option.accessor, value)}
description={option.description}
/>
))
}
]}
compute={computeExternal}
setInput={setInput}
exampleCards={exampleCards}
/>
);
}

View File

@@ -1,6 +1,5 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
import image from '@assets/text.png';
export const tool = defineTool('string', {
path: 'split',
@@ -9,6 +8,7 @@ export const tool = defineTool('string', {
description:
"World's simplest browser-based utility for splitting text. Load your text in the input form on the left and you'll automatically get pieces of this text on the right. Powerful, free, and fast. Load text get chunks.",
shortDescription: 'Quickly split a text',
longDescription: 'Quickly split a text',
keywords: ['text', 'split'],
component: lazy(() => import('./index'))
});

View File

@@ -34,7 +34,7 @@ function replaceTextWithRegexp(
return text.replace(new RegExp(searchRegexp, 'g'), replaceValue);
}
} catch (err) {
console.error('Invalid regular expression:', err);
// console.error('Invalid regular expression:', err);
return text;
}
}

View File

@@ -1,11 +1,9 @@
import { Box } from '@mui/material';
import ToolContent from '@components/ToolContent';
import React, { useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import ToolOptions from '@components/options/ToolOptions';
import { compute } from './service';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
const initialValues = {
dotSymbol: '.',
@@ -15,49 +13,46 @@ const initialValues = {
export default function ToMorse() {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
// const formRef = useRef<FormikProps<typeof initialValues>>(null);
const computeOptions = (optionsValues: typeof initialValues, input: any) => {
const { dotSymbol, dashSymbol } = optionsValues;
setResult(compute(input, dotSymbol, dashSymbol));
};
return (
<Box>
<ToolInputAndResult
input={<ToolTextInput value={input} onChange={setInput} />}
result={<ToolTextResult title={'Morse code'} value={result} />}
/>
<ToolOptions
compute={computeOptions}
getGroups={({ values, updateField }) => [
{
title: 'Short Signal',
component: (
<TextFieldWithDesc
description={
'Symbol that will correspond to the dot in Morse code.'
}
value={values.dotSymbol}
onOwnChange={(val) => updateField('dotSymbol', val)}
/>
)
},
{
title: 'Long Signal',
component: (
<TextFieldWithDesc
description={
'Symbol that will correspond to the dash in Morse code.'
}
value={values.dashSymbol}
onOwnChange={(val) => updateField('dashSymbol', val)}
/>
)
}
]}
initialValues={initialValues}
input={input}
/>
</Box>
<ToolContent
title="To Morse"
initialValues={initialValues}
compute={computeOptions}
input={input}
setInput={setInput}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={<ToolTextResult title={'Morse code'} value={result} />}
getGroups={({ values, updateField }) => [
{
title: 'Short Signal',
component: (
<TextFieldWithDesc
description={
'Symbol that will correspond to the dot in Morse code.'
}
value={values.dotSymbol}
onOwnChange={(val) => updateField('dotSymbol', val)}
/>
)
},
{
title: 'Long Signal',
component: (
<TextFieldWithDesc
description={
'Symbol that will correspond to the dash in Morse code.'
}
value={values.dashSymbol}
onOwnChange={(val) => updateField('dashSymbol', val)}
/>
)
}
]}
/>
);
}

View File

@@ -1,11 +1,63 @@
import { Box } from '@mui/material';
import React from 'react';
import * as Yup from 'yup';
import React, { useState } from 'react';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { UppercaseInput } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
const initialValues = {};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function Uppercase() {
return <Box>Lorem ipsum</Box>;
const exampleCards: CardExampleType<typeof initialValues>[] = [
{
title: 'Convert Text to Uppercase',
description: 'This example transforms any text to ALL UPPERCASE format.',
sampleText: 'The quick brown fox jumps over the lazy dog.',
sampleResult: 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.',
sampleOptions: {}
},
{
title: 'Uppercase Code',
description:
'Convert code to uppercase format. Note that this is for display only and would not maintain code functionality.',
sampleText: 'function example() { return "hello world"; }',
sampleResult: 'FUNCTION EXAMPLE() { RETURN "HELLO WORLD"; }',
sampleOptions: {}
},
{
title: 'Mixed Case to Uppercase',
description:
'Transform text with mixed casing to consistent all uppercase format.',
sampleText: 'ThIs Is MiXeD CaSe TeXt!',
sampleResult: 'THIS IS MIXED CASE TEXT!',
sampleOptions: {}
}
];
export default function Uppercase({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const computeExternal = (
_optionsValues: typeof initialValues,
input: string
) => {
setResult(UppercaseInput(input));
};
return (
<ToolContent
title={title}
initialValues={initialValues}
getGroups={null}
compute={computeExternal}
input={input}
setInput={setInput}
inputComponent={<ToolTextInput value={input} onChange={setInput} />}
resultComponent={
<ToolTextResult title={'Uppercase text'} value={result} />
}
exampleCards={exampleCards}
/>
);
}

View File

@@ -1,13 +1,13 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('string', {
name: 'Uppercase',
path: 'uppercase',
icon: '',
description: '',
shortDescription: '',
icon: 'material-symbols-light:text-fields',
description:
"World's simplest browser-based utility for converting text to uppercase. Just input your text and it will be automatically converted to all capital letters. Perfect for creating headlines, emphasizing text, or standardizing text format. Supports various text formats and preserves special characters.",
shortDescription: 'Convert text to uppercase letters',
keywords: ['uppercase'],
component: lazy(() => import('./index'))
});