Skip to content

Commit 2250824

Browse files
committed
Merge branch 'feat/unicode-formatter' into chore/all-my-stuffs
# Conflicts: # components.d.ts # src/tools/index.ts
2 parents 107864b + eac0de1 commit 2250824

File tree

6 files changed

+400
-0
lines changed

6 files changed

+400
-0
lines changed

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import { tool as sensitiveDataMasker } from './sensitive-data-masker';
8888
import { tool as textToUnicodeNames } from './text-to-unicode-names';
8989
import { tool as torrentToMagnet } from './torrent-to-magnet';
9090
import { tool as ttlCalculator } from './ttl-calculator';
91+
import { tool as unicodeFormatter } from './unicode-formatter';
9192
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
9293
import { tool as numeronymGenerator } from './numeronym-generator';
9394
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -401,6 +402,7 @@ export const toolsByCategory: ToolCategory[] = [
401402
icalParser,
402403
icalMerger,
403404
sensitiveDataMasker,
405+
unicodeFormatter,
404406
],
405407
},
406408
{

src/tools/unicode-formatter/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Edit } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Unicode Formatter',
6+
path: '/unicode-formatter',
7+
description: 'Format text using Unicode fonts',
8+
keywords: ['unicode', 'formatter', 'fonts'],
9+
component: () => import('./unicode-formatter.vue'),
10+
icon: Edit,
11+
createdAt: new Date('2024-04-07'),
12+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"normal": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",
3+
"sans": "\"\\ !#$%&'()*+,-./𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫:;<=>?@𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹[]^_`𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓{|}~",
4+
"sansBold": "\"\\ !#$%&'()*+,-./𝟬𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵:;<=>?@𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭[]^_`𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇{|}~",
5+
"sansItalic": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡[]^_`𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻{|}~",
6+
"sansBoldItalic": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕[]^_`𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯{|}~",
7+
"monospace": "\"\\ !#$%&'()*+,-./𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿:;<=>?@𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉[]^_`𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣{|}~",
8+
"fullwidth": "\"\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~",
9+
"fraktur": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ[]^_`𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷{|}~",
10+
"boldFraktur": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅[]^_`𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟{|}~",
11+
"serifBold": "\"\\ !#$%&'()*+,-./𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗:;<=>?@𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙[]^_`𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳{|}~",
12+
"serifItalic": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍[]^_`𝑎𝑏𝑐𝑑𝑒𝑓𝑔ℎ𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧{|}~",
13+
"serifBoldItalic": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁[]^_`𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛{|}~",
14+
"doubleStruck": "\"\\ !#$%&'()*+,-./𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡:;<=>?@𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ[]^_`𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫{|}~",
15+
"script": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵[]^_`𝒶𝒷𝒸𝒹ℯ𝒻ℊ𝒽𝒾𝒿𝓀𝓁𝓂𝓃ℴ𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏{|}~",
16+
"boldScript": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩[]^_`𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃{|}~",
17+
"circled": "\"⦸ !#$%&'()⊛⊕,⊖⨀⊘⓪①②③④⑤⑥⑦⑧⑨:;⧀⊜⧁?@ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ[]^_`ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ{⦶}~",
18+
"circledNegative": "\"\\ !#$%&'()*+,-./⓿❶❷❸❹❺❻❼❽❾:;<=>?@🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩[]^_`🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩{|}~",
19+
"squared": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉[]^_`🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉{|}~",
20+
"squaredNegative": "\"⧅ !#$%&'()⧆⊞,⊟⊡⧄0123456789:;<=>?@🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉[]^_`🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉{|}~",
21+
"parenthesized": "\"\\ !#$%&'()*+,-./0⑴⑵⑶⑷⑸⑹⑺⑻⑼:;<=>?@⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵[]^_`⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵{|}~",
22+
"smallCaps": "\"\\ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴩꞯʀꜱᴛᴜᴠᴡxʏᴢ{|}~",
23+
"subscript": "\"\\ !#$%&'₍₎*₊,₋./₀₁₂₃₄₅₆₇₈₉:;<₌>?@ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘ🇶ʀꜱᴛᴜᴠᴡxʏᴢ[]^_`ₐᵦ𝒸𝒹ₑ𝒻𝓰ₕᵢⱼₖₗₘₙₒₚᵩᵣₛₜᵤᵥ𝓌ₓᵧ𝓏{|}~",
24+
"superscript": "\"\\ !#$%&'⁽⁾*⁺,⁻./⁰¹²³⁴⁵⁶⁷⁸⁹:;<⁼>?@ᴬᴮᶜᴰᴱᶠᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾᵠᴿˢᵀᵁⱽᵂˣʸᶻ[]^_`ᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖᵠʳˢᵗᵘᵛʷˣʸᶻ{|}~",
25+
"inverted": "\\ ¡#$%⅋,)(*+‘-˙/0ƖՇƐᔭϛ9𝘓86:;<=>¿@∀ꓭↃꓷƎℲ⅁HIſꓘ⅂WNOԀῸꓤS⊥∩ꓥMX⅄Z][^‾`ɐqɔpǝɟƃɥıɾʞןɯuodbɹsʇnʌʍxʎz}|{~",
26+
"mirrored": "\"/ !#$%&')(*+,-.\\0߁ςƐ߂टმ٢8୧:;<=>⸮@AꓭↃꓷƎꟻӘHIႱꓘ⅃MИOꟼϘЯꙄTUVWXYZ][^_`ɒdↄbɘʇϱʜiįʞlmᴎoqpᴙꙅɈυvwxγz}|{~",
27+
"rotatedLeft": "=/ !#$%&-⏝⏜*+`ǀ∙\\ⴰ↽വ𝈐ፓහமΓꝏᓂ⠒;˅𝄥∧ᣇ@ᗉߘ𝈱⌓ш𝈯ᘎ⌶𝄩⥟𝈎⨼∑Zⴰᓇⵚᓚᔕ⊢⊃𝈷ᕒ×⤚𝇙⎵⎴‹|`ơᓄ𝈱ᓀш𝈯თ𝈦𝄩ᓜ𝈎⨼ᗴ⊂ⴰᓇᓂᓚᔕ𝀏⊃𝈷З×⤚𝇙⏟_⏞ಽ",
28+
"rotatedRight": "=/ !#$%&-⏜⏝*+`ǀ∙\\ⴰ⇀ᘚω𝈦හの⨼ꝏᓄ⠒;∧𝄥˅?@ᗆϖᴒᗜጠ╖ᘏ⌶𝄩ᓚ⌤⌐ᕒZⴰᓀᓄᓓᔕ⊣⊂<ᓬ×⤙𝇙⎴⎵›|`⌕ᓂᴒ௨ጠ╖மፓ𝄩ᓚ⌤⌐ᴟᴝⴰᓀᓄᓓᔕ𝀏⊂<ᓬ×⤙𝇙⏞_⏟ಽ"
29+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { formatTextPart } from './unicode-formatter.service';
3+
4+
describe('unicode-formatter', () => {
5+
it('formatTextPart applies correct style/font on text part', async () => {
6+
expect(formatTextPart('The quick fox', 4, 9, 'sansBold')).to.deep.equal({
7+
from: 4,
8+
text: 'The 𝗾𝘂𝗶𝗰𝗸 fox',
9+
to: 14,
10+
});
11+
expect(formatTextPart('The quick fox', 4, 13, 'boldScript')).to.deep.equal({
12+
from: 4,
13+
text: 'The 𝓺𝓾𝓲𝓬𝓴 𝓯𝓸𝔁',
14+
to: 21,
15+
});
16+
expect(formatTextPart('The quick fox', 4, 6, 'smallCaps')).to.deep.equal({
17+
from: 4,
18+
text: 'The ꞯᴜick fox',
19+
to: 6,
20+
});
21+
expect(formatTextPart('The quick fox', 4, 8, 'inverted')).to.deep.equal({
22+
from: 4,
23+
text: 'The bnıɔk fox',
24+
to: 8,
25+
});
26+
expect(formatTextPart('The quick fox', 4, 10, 'mirrored')).to.deep.equal({
27+
from: 4,
28+
text: 'The pυiↄʞ fox',
29+
to: 10,
30+
});
31+
expect(formatTextPart('The quick fox', 4, 11, 'serifBoldItalic')).to.deep.equal({
32+
from: 4,
33+
text: 'The 𝒒𝒖𝒊𝒄𝒌 𝒇ox',
34+
to: 17,
35+
});
36+
});
37+
38+
it('formatTextPart un-applies correct style/font on text part', async () => {
39+
expect(formatTextPart('The 𝗾𝘂𝗶𝗰𝗸 fox', 4, 14, 'sansBold')).to.deep.equal({
40+
from: 4,
41+
text: 'The quick fox',
42+
to: 9,
43+
});
44+
expect(formatTextPart('The 𝓺𝓾𝓲𝓬𝓴 𝓯𝓸𝔁', 4, 18, 'boldScript')).to.deep.equal({
45+
from: 4,
46+
text: 'The quick f𝓸𝔁',
47+
to: 12,
48+
});
49+
expect(formatTextPart('The 𝓺𝓾𝓲𝓬𝓴 𝓯𝓸𝔁', 4, 14, 'boldScript')).to.deep.equal({
50+
from: 4,
51+
text: 'The quick 𝓯𝓸𝔁',
52+
to: 9,
53+
});
54+
expect(formatTextPart('The 𝓺𝓾𝓲𝓬𝓴 fox', 4, 15, 'boldScript')).to.deep.equal({
55+
from: 4,
56+
text: 'The quick fox',
57+
to: 10,
58+
});
59+
expect(formatTextPart('The pυiↄʞ fox', 4, 10, 'mirrored')).to.deep.equal({
60+
from: 4,
61+
text: 'The puick fox', // can't be fully restored
62+
to: 10,
63+
});
64+
expect(formatTextPart('The bnıɔk fox', 4, 10, 'inverted')).to.deep.equal({
65+
from: 4,
66+
text: 'The quıɔʞ fox',
67+
to: 10,
68+
});
69+
expect(formatTextPart('The 𝒒𝒖𝒊𝒄𝒌 𝒇ox', 4, 17, 'serifBoldItalic')).to.deep.equal({
70+
from: 4,
71+
text: 'The quick fox',
72+
to: 11,
73+
});
74+
});
75+
});
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// prettier-ignore
2+
import fonts from './unicode-fonts.json';
3+
4+
export type AllFontNames = keyof typeof fonts;
5+
export interface AllOptions {
6+
remove?: string
7+
append?: string
8+
reverse?: boolean
9+
clear?: boolean
10+
};
11+
12+
// list of font characters for checking if character is formatted
13+
const allCharacters = new Set(Object.values(fonts).join(''));
14+
15+
// check if text is already formatted with a certain font
16+
function alreadyFormatted(text: string, font: AllFontNames) {
17+
const fontCharacters = new Set(fonts[font]);
18+
// flag as already formatted if all characters are in font or not in any other font
19+
return Array.from(text).every(char => fontCharacters.has(char) || !allCharacters.has(char));
20+
}
21+
22+
// check if text is already formatted with a certain font
23+
function alreadyAppended(text: string, append: string) {
24+
// check if at least half the characters are the append character
25+
return Array.from(text).filter(char => char === append).length >= text.length / 2;
26+
}
27+
28+
// format text into selected font
29+
function formatText(text: string, font: AllFontNames | undefined, options?: AllOptions) {
30+
// set font to normal if already formatted with selected font
31+
if (font && fonts[font] && alreadyFormatted(text, font)) {
32+
font = 'normal';
33+
}
34+
// remove and don't append if character is already appended
35+
if (options?.append) {
36+
options.remove = options.append;
37+
options.append = !alreadyAppended(text, options.append) ? options.append : '';
38+
}
39+
// Array.from() splits the string by symbol and not by code points
40+
let newText = Array.from(text);
41+
// exchange font symbols
42+
if (font && fonts[font]) {
43+
const targetFont = Array.from(fonts[font]);
44+
const charLists = Object.values(fonts);
45+
// map characters to new font
46+
newText = newText.map((char) => {
47+
let index = -1;
48+
// find the index of the character in some font
49+
const found = charLists.some((charList) => {
50+
index = Array.from(charList).indexOf(char);
51+
return index > -1;
52+
});
53+
// if found, replace with the corresponding character in the target font
54+
// if not found, keep the character the same
55+
return found ? targetFont[index] : char;
56+
});
57+
}
58+
// reverse text if reverse option is set
59+
newText = options?.reverse ? newText.reverse() : newText;
60+
// remove appended symbol of specific type from the end
61+
newText = options?.remove
62+
? newText.map(char => char.replace(new RegExp(`${options.remove}$`, 'u'), ''))
63+
: newText;
64+
// append symbol (underline, strikethrough, etc.) to end of each character if append is set
65+
newText = options?.append ? newText.map(char => char + options.append) : newText;
66+
// remove appended symbols (underline, strikethrough, etc.) if using eraser
67+
// \u035f = Underline, \u0333 = Double Underline, \u0335 = Short Strikethrough \u0336 = Strikethrough
68+
newText = options?.clear ? newText.map(char => char.replace(/\u035F|\u0333|\u0335|\u0336/gu, '')) : newText;
69+
// set textarea content and select text around the replacement
70+
return newText.join('');
71+
}
72+
73+
export function formatTextPart(
74+
text: string,
75+
selectionStart: number, selectionEnd: number,
76+
font: AllFontNames | undefined,
77+
options?: AllOptions) {
78+
const regexSpaces = /^(\s*)(.+?)(\s*)$/g; // NOSONAR
79+
const [_, spaceBefore, selection, spaceAfter] = regexSpaces.exec(text.substring(selectionStart, selectionEnd) || '') || [];
80+
81+
const prefix = text.substring(0, selectionStart);
82+
const newSelection = formatText(selection, font, options);
83+
const suffix = text.substring(selectionEnd);
84+
return {
85+
text: `${prefix}${spaceBefore}${newSelection}${spaceAfter}${suffix}`,
86+
from: selectionStart,
87+
to: selectionStart + (spaceBefore?.length || 0) + newSelection.length + (spaceAfter?.length || 0),
88+
};
89+
}
90+
91+
// format selected text
92+
export function formatSelection(textArea: HTMLTextAreaElement, font: AllFontNames | undefined, options?: AllOptions) {
93+
const selectionStart = textArea.selectionStart;
94+
const selectionEnd = textArea.selectionEnd;
95+
const oldText = textArea.value;
96+
97+
const { text: newText, from, to } = formatTextPart(oldText, selectionStart, selectionEnd, font, options);
98+
99+
textArea.value = newText;
100+
textArea.setSelectionRange(from, to);
101+
102+
textArea.focus();
103+
}

0 commit comments

Comments
 (0)