Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions dprint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"typescript": {
"typeLiteral.separatorKind": "comma",
"quoteStyle": "preferSingle",
"jsx.quoteStyle": "preferDouble"
},
"json": {
},
"includes": [
"src/**/*.{ts,tsx,js,jsx,cjs,mjs}",
"test/**/*.{ts,tsx,js,jsx,cjs,mjs}",
"./*.json"
],
"excludes": [
"**/node_modules",
"**/*-lock.json"
],
"plugins": [
"https://plugins.dprint.dev/typescript-0.96.1.wasm",
"https://plugins.dprint.dev/json-0.23.0.wasm"
]
}
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,14 @@
"homepage": "https://github.com/u-wave/parse-chat-markup#readme",
"scripts": {
"prepare": "tsdown src/index.ts --format esm,cjs --dts",
"lint": "eslint .",
"lint": "oxlint src && dprint check",
"test": "npm run tests-only && npm run lint",
"tests-only": "vitest run --coverage.enabled --coverage.reporter=lcov --coverage.reporter=text --coverage.100"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.2.0",
"@typescript-eslint/parser": "^8.2.0",
"@vitest/coverage-v8": "^4.1.0",
"eslint": "^8.2.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.22.0",
"dprint": "^0.55.2",
"oxlint": "^1.78.0",
"tsdown": "^0.22.0",
"typescript": "^6.0.3",
"vitest": "^4.1.0"
Expand Down
57 changes: 33 additions & 24 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,17 @@ describe('parseChatMarkup', () => {
});

it('parses :emoji: that could also be italics', () => {
assert.deepStrictEqual(parseChatMarkup('_it\'s :emoji_time:!', bareOptions), [
'_it\'s ',
assert.deepStrictEqual(parseChatMarkup("_it's :emoji_time:!", bareOptions), [
"_it's ",
{ type: 'emoji', name: 'emoji_time' },
'!',
]);

assert.deepStrictEqual(parseChatMarkup('_it\'s :emoji_time:!_', bareOptions), [
assert.deepStrictEqual(parseChatMarkup("_it's :emoji_time:!_", bareOptions), [
{
type: 'italic',
content: [
'it\'s ',
"it's ",
{ type: 'emoji', name: 'emoji_time' },
'!',
],
Expand Down Expand Up @@ -208,29 +208,38 @@ describe('parseChatMarkup', () => {
});

it('parses @-mentions with punctuation in them', () => {
assert.deepStrictEqual(parseChatMarkup('@user[AFK] hello!', {
mentions: ['user[AFK]'],
}), [
{ type: 'mention', mention: 'user[afk]', raw: 'user[AFK]' },
' hello!',
]);

assert.deepStrictEqual(parseChatMarkup('hello @user[AFK]', {
mentions: ['user[AFK]'],
}), [
'hello ',
{ type: 'mention', mention: 'user[afk]', raw: 'user[AFK]' },
]);
assert.deepStrictEqual(
parseChatMarkup('@user[AFK] hello!', {
mentions: ['user[AFK]'],
}),
[
{ type: 'mention', mention: 'user[afk]', raw: 'user[AFK]' },
' hello!',
],
);

assert.deepStrictEqual(
parseChatMarkup('hello @user[AFK]', {
mentions: ['user[AFK]'],
}),
[
'hello ',
{ type: 'mention', mention: 'user[afk]', raw: 'user[AFK]' },
],
);
});

it('parses @-mentions with no clear word boundary', () => {
assert.deepStrictEqual(parseChatMarkup('hello @ReAnna!!!', {
mentions: ['ReAnna!!'],
}), [
'hello ',
{ type: 'mention', mention: 'reanna!!', raw: 'ReAnna!!' },
'!',
]);
assert.deepStrictEqual(
parseChatMarkup('hello @ReAnna!!!', {
mentions: ['ReAnna!!'],
}),
[
'hello ',
{ type: 'mention', mention: 'reanna!!', raw: 'ReAnna!!' },
'!',
],
);
});
});
});
15 changes: 8 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,16 @@ function createToken(type: TokenType, text: string, raw: string = text): Token {
* Sort users by username length. Longest usernames first.
*/
const sortMentions = memoize((mentions: string[]): string[] => (
mentions.slice().sort((a, b) => b.length - a.length)));

const makeMentionRegExp = memoize((mentions: string[]): RegExp => new RegExp(
`^(${
mentions.map((mention) => escapeStringRegExp(mention)).join('|')
})(?:\\b|\\s|\\W|$)`,
'i',
mentions.slice().sort((a, b) => b.length - a.length)
));

const makeMentionRegExp = memoize((mentions: string[]): RegExp =>
new RegExp(
`^(${mentions.map((mention) => escapeStringRegExp(mention)).join('|')})(?:\\b|\\s|\\W|$)`,
'i',
)
);

/**
* Case-insensitively get the correct emoji name from the possible emoji for an
* input string.
Expand Down