@atproto/api 0.10.1 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/bsky-agent.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +77 -57
- package/dist/index.js.map +3 -3
- package/dist/util.d.ts +1 -0
- package/package.json +6 -6
- package/src/bsky-agent.ts +97 -74
- package/src/client/lexicons.ts +1 -1
- package/src/index.ts +1 -0
- package/src/rich-text/detection.ts +6 -8
- package/src/util.ts +6 -0
- package/tests/bsky-agent.test.ts +139 -8
- package/tests/rich-text-detection.test.ts +26 -4
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sanitizeMutedWordValue(value: string): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/api",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Client library for atproto and Bluesky",
|
|
6
6
|
"keywords": [
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
"typed-emitter": "^2.1.0",
|
|
22
22
|
"zod": "^3.21.4",
|
|
23
23
|
"@atproto/common-web": "^0.2.3",
|
|
24
|
-
"@atproto/lexicon": "^0.3.
|
|
25
|
-
"@atproto/syntax": "^0.
|
|
26
|
-
"@atproto/xrpc": "^0.4.
|
|
24
|
+
"@atproto/lexicon": "^0.3.2",
|
|
25
|
+
"@atproto/syntax": "^0.2.0",
|
|
26
|
+
"@atproto/xrpc": "^0.4.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"common-tags": "^1.8.2",
|
|
30
|
-
"@atproto/lex-cli": "^0.3.
|
|
31
|
-
"@atproto/dev-env": "^0.2.
|
|
30
|
+
"@atproto/lex-cli": "^0.3.1",
|
|
31
|
+
"@atproto/dev-env": "^0.2.35"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"codegen": "pnpm docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
|
package/src/bsky-agent.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
BskyThreadViewPreference,
|
|
14
14
|
BskyInterestsPreference,
|
|
15
15
|
} from './types'
|
|
16
|
+
import { sanitizeMutedWordValue } from './util'
|
|
16
17
|
|
|
17
18
|
const FEED_VIEW_PREF_DEFAULTS = {
|
|
18
19
|
hideReplies: false,
|
|
@@ -565,16 +566,108 @@ export class BskyAgent extends AtpAgent {
|
|
|
565
566
|
})
|
|
566
567
|
}
|
|
567
568
|
|
|
568
|
-
async upsertMutedWords(
|
|
569
|
-
await
|
|
569
|
+
async upsertMutedWords(newMutedWords: AppBskyActorDefs.MutedWord[]) {
|
|
570
|
+
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
571
|
+
let mutedWordsPref = prefs.findLast(
|
|
572
|
+
(pref) =>
|
|
573
|
+
AppBskyActorDefs.isMutedWordsPref(pref) &&
|
|
574
|
+
AppBskyActorDefs.validateMutedWordsPref(pref).success,
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
578
|
+
for (const updatedWord of newMutedWords) {
|
|
579
|
+
let foundMatch = false
|
|
580
|
+
const sanitizedUpdatedValue = sanitizeMutedWordValue(
|
|
581
|
+
updatedWord.value,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
// was trimmed down to an empty string e.g. single `#`
|
|
585
|
+
if (!sanitizedUpdatedValue) continue
|
|
586
|
+
|
|
587
|
+
for (const existingItem of mutedWordsPref.items) {
|
|
588
|
+
if (existingItem.value === sanitizedUpdatedValue) {
|
|
589
|
+
existingItem.targets = Array.from(
|
|
590
|
+
new Set([...existingItem.targets, ...updatedWord.targets]),
|
|
591
|
+
)
|
|
592
|
+
foundMatch = true
|
|
593
|
+
break
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (!foundMatch) {
|
|
598
|
+
mutedWordsPref.items.push({
|
|
599
|
+
...updatedWord,
|
|
600
|
+
value: sanitizedUpdatedValue,
|
|
601
|
+
})
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
} else {
|
|
605
|
+
// if the pref doesn't exist, create it
|
|
606
|
+
mutedWordsPref = {
|
|
607
|
+
items: newMutedWords.map((w) => ({
|
|
608
|
+
...w,
|
|
609
|
+
value: sanitizeMutedWordValue(w.value),
|
|
610
|
+
})),
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
return prefs
|
|
615
|
+
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
616
|
+
.concat([
|
|
617
|
+
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
618
|
+
])
|
|
619
|
+
})
|
|
570
620
|
}
|
|
571
621
|
|
|
572
622
|
async updateMutedWord(mutedWord: AppBskyActorDefs.MutedWord) {
|
|
573
|
-
await
|
|
623
|
+
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
624
|
+
let mutedWordsPref = prefs.findLast(
|
|
625
|
+
(pref) =>
|
|
626
|
+
AppBskyActorDefs.isMutedWordsPref(pref) &&
|
|
627
|
+
AppBskyActorDefs.validateMutedWordsPref(pref).success,
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
631
|
+
for (const existingItem of mutedWordsPref.items) {
|
|
632
|
+
if (existingItem.value === mutedWord.value) {
|
|
633
|
+
existingItem.targets = mutedWord.targets
|
|
634
|
+
break
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return prefs
|
|
640
|
+
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
641
|
+
.concat([
|
|
642
|
+
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
643
|
+
])
|
|
644
|
+
})
|
|
574
645
|
}
|
|
575
646
|
|
|
576
647
|
async removeMutedWord(mutedWord: AppBskyActorDefs.MutedWord) {
|
|
577
|
-
await
|
|
648
|
+
await updatePreferences(this, (prefs: AppBskyActorDefs.Preferences) => {
|
|
649
|
+
let mutedWordsPref = prefs.findLast(
|
|
650
|
+
(pref) =>
|
|
651
|
+
AppBskyActorDefs.isMutedWordsPref(pref) &&
|
|
652
|
+
AppBskyActorDefs.validateMutedWordsPref(pref).success,
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
656
|
+
for (let i = 0; i < mutedWordsPref.items.length; i++) {
|
|
657
|
+
const existing = mutedWordsPref.items[i]
|
|
658
|
+
if (existing.value === mutedWord.value) {
|
|
659
|
+
mutedWordsPref.items.splice(i, 1)
|
|
660
|
+
break
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return prefs
|
|
666
|
+
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
667
|
+
.concat([
|
|
668
|
+
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
669
|
+
])
|
|
670
|
+
})
|
|
578
671
|
}
|
|
579
672
|
|
|
580
673
|
async hidePost(postUri: string) {
|
|
@@ -646,76 +739,6 @@ async function updateFeedPreferences(
|
|
|
646
739
|
return res
|
|
647
740
|
}
|
|
648
741
|
|
|
649
|
-
/**
|
|
650
|
-
* A helper specifically for updating muted words preferences
|
|
651
|
-
*/
|
|
652
|
-
async function updateMutedWords(
|
|
653
|
-
agent: BskyAgent,
|
|
654
|
-
mutedWords: AppBskyActorDefs.MutedWord[],
|
|
655
|
-
action: 'upsert' | 'update' | 'remove',
|
|
656
|
-
) {
|
|
657
|
-
const sanitizeMutedWord = (word: AppBskyActorDefs.MutedWord) => ({
|
|
658
|
-
value: word.value.replace(/^#/, ''),
|
|
659
|
-
targets: word.targets,
|
|
660
|
-
})
|
|
661
|
-
|
|
662
|
-
await updatePreferences(agent, (prefs: AppBskyActorDefs.Preferences) => {
|
|
663
|
-
let mutedWordsPref = prefs.findLast(
|
|
664
|
-
(pref) =>
|
|
665
|
-
AppBskyActorDefs.isMutedWordsPref(pref) &&
|
|
666
|
-
AppBskyActorDefs.validateMutedWordsPref(pref).success,
|
|
667
|
-
)
|
|
668
|
-
|
|
669
|
-
if (mutedWordsPref && AppBskyActorDefs.isMutedWordsPref(mutedWordsPref)) {
|
|
670
|
-
if (action === 'upsert' || action === 'update') {
|
|
671
|
-
for (const newItem of mutedWords) {
|
|
672
|
-
let foundMatch = false
|
|
673
|
-
|
|
674
|
-
for (const existingItem of mutedWordsPref.items) {
|
|
675
|
-
if (existingItem.value === newItem.value) {
|
|
676
|
-
existingItem.targets =
|
|
677
|
-
action === 'upsert'
|
|
678
|
-
? Array.from(
|
|
679
|
-
new Set([...existingItem.targets, ...newItem.targets]),
|
|
680
|
-
)
|
|
681
|
-
: newItem.targets
|
|
682
|
-
foundMatch = true
|
|
683
|
-
break
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
if (action === 'upsert' && !foundMatch) {
|
|
688
|
-
mutedWordsPref.items.push(sanitizeMutedWord(newItem))
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
} else if (action === 'remove') {
|
|
692
|
-
for (const word of mutedWords) {
|
|
693
|
-
for (let i = 0; i < mutedWordsPref.items.length; i++) {
|
|
694
|
-
const existing = mutedWordsPref.items[i]
|
|
695
|
-
if (existing.value === sanitizeMutedWord(word).value) {
|
|
696
|
-
mutedWordsPref.items.splice(i, 1)
|
|
697
|
-
break
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
} else {
|
|
703
|
-
// if the pref doesn't exist, create it
|
|
704
|
-
if (action === 'upsert') {
|
|
705
|
-
mutedWordsPref = {
|
|
706
|
-
items: mutedWords.map(sanitizeMutedWord),
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
return prefs
|
|
712
|
-
.filter((p) => !AppBskyActorDefs.isMutedWordsPref(p))
|
|
713
|
-
.concat([
|
|
714
|
-
{ ...mutedWordsPref, $type: 'app.bsky.actor.defs#mutedWordsPref' },
|
|
715
|
-
])
|
|
716
|
-
})
|
|
717
|
-
}
|
|
718
|
-
|
|
719
742
|
async function updateHiddenPost(
|
|
720
743
|
agent: BskyAgent,
|
|
721
744
|
postUri: string,
|
package/src/client/lexicons.ts
CHANGED
|
@@ -4867,7 +4867,7 @@ export const schemaDict = {
|
|
|
4867
4867
|
main: {
|
|
4868
4868
|
type: 'query',
|
|
4869
4869
|
description:
|
|
4870
|
-
'Fetch all labels from a labeler created after a certain date.
|
|
4870
|
+
'DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.',
|
|
4871
4871
|
parameters: {
|
|
4872
4872
|
type: 'params',
|
|
4873
4873
|
properties: {
|
package/src/index.ts
CHANGED
|
@@ -70,27 +70,25 @@ export function detectFacets(text: UnicodeString): Facet[] | undefined {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
{
|
|
73
|
-
const re = /(
|
|
73
|
+
const re = /(^|\s)#((?!\ufe0f)[^\d\s]\S*)(?=\s)?/g
|
|
74
74
|
while ((match = re.exec(text.utf16))) {
|
|
75
|
-
let [tag] = match
|
|
76
|
-
const hasLeadingSpace = /^\s/.test(tag)
|
|
75
|
+
let [, leading, tag] = match
|
|
77
76
|
|
|
78
77
|
tag = tag.trim().replace(/\p{P}+$/gu, '') // strip ending punctuation
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
if (tag.length > 66) continue
|
|
79
|
+
if (tag.length === 0 || tag.length > 64) continue
|
|
82
80
|
|
|
83
|
-
const index = match.index +
|
|
81
|
+
const index = match.index + leading.length
|
|
84
82
|
|
|
85
83
|
facets.push({
|
|
86
84
|
index: {
|
|
87
85
|
byteStart: text.utf16IndexToUtf8Index(index),
|
|
88
|
-
byteEnd: text.utf16IndexToUtf8Index(index + tag.length),
|
|
86
|
+
byteEnd: text.utf16IndexToUtf8Index(index + 1 + tag.length),
|
|
89
87
|
},
|
|
90
88
|
features: [
|
|
91
89
|
{
|
|
92
90
|
$type: 'app.bsky.richtext.facet#tag',
|
|
93
|
-
tag: tag
|
|
91
|
+
tag: tag,
|
|
94
92
|
},
|
|
95
93
|
],
|
|
96
94
|
})
|
package/src/util.ts
ADDED
package/tests/bsky-agent.test.ts
CHANGED
|
@@ -1199,10 +1199,22 @@ describe('agent', () => {
|
|
|
1199
1199
|
})
|
|
1200
1200
|
|
|
1201
1201
|
it('upsertMutedWords with #', async () => {
|
|
1202
|
+
await agent.upsertMutedWords([
|
|
1203
|
+
{ value: 'hashtag', targets: ['content'] },
|
|
1204
|
+
])
|
|
1205
|
+
// is sanitized to `hashtag`
|
|
1202
1206
|
await agent.upsertMutedWords([{ value: '#hashtag', targets: ['tag'] }])
|
|
1207
|
+
|
|
1203
1208
|
const { mutedWords } = await agent.getPreferences()
|
|
1209
|
+
|
|
1204
1210
|
expect(mutedWords.find((m) => m.value === '#hashtag')).toBeFalsy()
|
|
1205
|
-
|
|
1211
|
+
// merged with existing
|
|
1212
|
+
expect(mutedWords.find((m) => m.value === 'hashtag')).toStrictEqual({
|
|
1213
|
+
value: 'hashtag',
|
|
1214
|
+
targets: ['content', 'tag'],
|
|
1215
|
+
})
|
|
1216
|
+
// only one added
|
|
1217
|
+
expect(mutedWords.filter((m) => m.value === 'hashtag').length).toBe(1)
|
|
1206
1218
|
})
|
|
1207
1219
|
|
|
1208
1220
|
it('updateMutedWord', async () => {
|
|
@@ -1230,15 +1242,21 @@ describe('agent', () => {
|
|
|
1230
1242
|
expect(mutedWords.find((m) => m.value === 'no_exist')).toBeFalsy()
|
|
1231
1243
|
})
|
|
1232
1244
|
|
|
1233
|
-
it('updateMutedWord with
|
|
1245
|
+
it('updateMutedWord with #, does not update', async () => {
|
|
1246
|
+
await agent.upsertMutedWords([
|
|
1247
|
+
{
|
|
1248
|
+
value: '#just_a_tag',
|
|
1249
|
+
targets: ['tag'],
|
|
1250
|
+
},
|
|
1251
|
+
])
|
|
1234
1252
|
await agent.updateMutedWord({
|
|
1235
|
-
value: '
|
|
1253
|
+
value: '#just_a_tag',
|
|
1236
1254
|
targets: ['tag', 'content'],
|
|
1237
1255
|
})
|
|
1238
1256
|
const { mutedWords } = await agent.getPreferences()
|
|
1239
|
-
expect(mutedWords.find((m) => m.value === '
|
|
1240
|
-
value: '
|
|
1241
|
-
targets: ['tag'
|
|
1257
|
+
expect(mutedWords.find((m) => m.value === 'just_a_tag')).toStrictEqual({
|
|
1258
|
+
value: 'just_a_tag',
|
|
1259
|
+
targets: ['tag'],
|
|
1242
1260
|
})
|
|
1243
1261
|
})
|
|
1244
1262
|
|
|
@@ -1255,11 +1273,124 @@ describe('agent', () => {
|
|
|
1255
1273
|
expect(mutedWords.find((m) => m.value === 'tag_then_none')).toBeFalsy()
|
|
1256
1274
|
})
|
|
1257
1275
|
|
|
1258
|
-
it('removeMutedWord with
|
|
1276
|
+
it('removeMutedWord with #, no match, no removal', async () => {
|
|
1259
1277
|
await agent.removeMutedWord({ value: '#hashtag', targets: [] })
|
|
1260
1278
|
const { mutedWords } = await agent.getPreferences()
|
|
1261
1279
|
|
|
1262
|
-
|
|
1280
|
+
// was inserted with #hashtag, but we don't sanitize on remove
|
|
1281
|
+
expect(mutedWords.find((m) => m.value === 'hashtag')).toBeTruthy()
|
|
1282
|
+
})
|
|
1283
|
+
|
|
1284
|
+
it('single-hash #', async () => {
|
|
1285
|
+
const prev = await agent.getPreferences()
|
|
1286
|
+
const length = prev.mutedWords.length
|
|
1287
|
+
await agent.upsertMutedWords([{ value: '#', targets: [] }])
|
|
1288
|
+
const end = await agent.getPreferences()
|
|
1289
|
+
|
|
1290
|
+
// sanitized to empty string, not inserted
|
|
1291
|
+
expect(end.mutedWords.length).toEqual(length)
|
|
1292
|
+
})
|
|
1293
|
+
|
|
1294
|
+
it('multi-hash ##', async () => {
|
|
1295
|
+
await agent.upsertMutedWords([{ value: '##', targets: [] }])
|
|
1296
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1297
|
+
|
|
1298
|
+
expect(mutedWords.find((m) => m.value === '#')).toBeTruthy()
|
|
1299
|
+
})
|
|
1300
|
+
|
|
1301
|
+
it('multi-hash ##hashtag', async () => {
|
|
1302
|
+
await agent.upsertMutedWords([{ value: '##hashtag', targets: [] }])
|
|
1303
|
+
const a = await agent.getPreferences()
|
|
1304
|
+
|
|
1305
|
+
expect(a.mutedWords.find((w) => w.value === '#hashtag')).toBeTruthy()
|
|
1306
|
+
|
|
1307
|
+
await agent.removeMutedWord({ value: '#hashtag', targets: [] })
|
|
1308
|
+
const b = await agent.getPreferences()
|
|
1309
|
+
|
|
1310
|
+
expect(b.mutedWords.find((w) => w.value === '#hashtag')).toBeFalsy()
|
|
1311
|
+
})
|
|
1312
|
+
|
|
1313
|
+
it('hash emoji #️⃣', async () => {
|
|
1314
|
+
await agent.upsertMutedWords([{ value: '#️⃣', targets: [] }])
|
|
1315
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1316
|
+
|
|
1317
|
+
expect(mutedWords.find((m) => m.value === '#️⃣')).toBeTruthy()
|
|
1318
|
+
|
|
1319
|
+
await agent.removeMutedWord({ value: '#️⃣', targets: [] })
|
|
1320
|
+
const end = await agent.getPreferences()
|
|
1321
|
+
|
|
1322
|
+
expect(end.mutedWords.find((m) => m.value === '#️⃣')).toBeFalsy()
|
|
1323
|
+
})
|
|
1324
|
+
|
|
1325
|
+
it('hash emoji ##️⃣', async () => {
|
|
1326
|
+
await agent.upsertMutedWords([{ value: '##️⃣', targets: [] }])
|
|
1327
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1328
|
+
|
|
1329
|
+
expect(mutedWords.find((m) => m.value === '#️⃣')).toBeTruthy()
|
|
1330
|
+
|
|
1331
|
+
await agent.removeMutedWord({ value: '#️⃣', targets: [] })
|
|
1332
|
+
const end = await agent.getPreferences()
|
|
1333
|
+
|
|
1334
|
+
expect(end.mutedWords.find((m) => m.value === '#️⃣')).toBeFalsy()
|
|
1335
|
+
})
|
|
1336
|
+
|
|
1337
|
+
it('hash emoji ###️⃣', async () => {
|
|
1338
|
+
await agent.upsertMutedWords([{ value: '###️⃣', targets: [] }])
|
|
1339
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1340
|
+
|
|
1341
|
+
expect(mutedWords.find((m) => m.value === '##️⃣')).toBeTruthy()
|
|
1342
|
+
|
|
1343
|
+
await agent.removeMutedWord({ value: '##️⃣', targets: [] })
|
|
1344
|
+
const end = await agent.getPreferences()
|
|
1345
|
+
|
|
1346
|
+
expect(end.mutedWords.find((m) => m.value === '##️⃣')).toBeFalsy()
|
|
1347
|
+
})
|
|
1348
|
+
|
|
1349
|
+
describe(`invalid characters`, () => {
|
|
1350
|
+
it('zero width space', async () => {
|
|
1351
|
+
const prev = await agent.getPreferences()
|
|
1352
|
+
const length = prev.mutedWords.length
|
|
1353
|
+
await agent.upsertMutedWords([{ value: '#', targets: [] }])
|
|
1354
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1355
|
+
|
|
1356
|
+
expect(mutedWords.length).toEqual(length)
|
|
1357
|
+
})
|
|
1358
|
+
|
|
1359
|
+
it('newline', async () => {
|
|
1360
|
+
await agent.upsertMutedWords([
|
|
1361
|
+
{ value: 'test value\n with newline', targets: [] },
|
|
1362
|
+
])
|
|
1363
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1364
|
+
|
|
1365
|
+
expect(
|
|
1366
|
+
mutedWords.find((m) => m.value === 'test value with newline'),
|
|
1367
|
+
).toBeTruthy()
|
|
1368
|
+
})
|
|
1369
|
+
|
|
1370
|
+
it('newline(s)', async () => {
|
|
1371
|
+
await agent.upsertMutedWords([
|
|
1372
|
+
{ value: 'test value\n\r with newline', targets: [] },
|
|
1373
|
+
])
|
|
1374
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1375
|
+
|
|
1376
|
+
expect(
|
|
1377
|
+
mutedWords.find((m) => m.value === 'test value with newline'),
|
|
1378
|
+
).toBeTruthy()
|
|
1379
|
+
})
|
|
1380
|
+
|
|
1381
|
+
it('empty space', async () => {
|
|
1382
|
+
await agent.upsertMutedWords([{ value: ' ', targets: [] }])
|
|
1383
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1384
|
+
|
|
1385
|
+
expect(mutedWords.find((m) => m.value === ' ')).toBeFalsy()
|
|
1386
|
+
})
|
|
1387
|
+
|
|
1388
|
+
it('leading/trailing space', async () => {
|
|
1389
|
+
await agent.upsertMutedWords([{ value: ' trim ', targets: [] }])
|
|
1390
|
+
const { mutedWords } = await agent.getPreferences()
|
|
1391
|
+
|
|
1392
|
+
expect(mutedWords.find((m) => m.value === 'trim')).toBeTruthy()
|
|
1393
|
+
})
|
|
1263
1394
|
})
|
|
1264
1395
|
})
|
|
1265
1396
|
|
|
@@ -241,15 +241,16 @@ describe('detectFacets', () => {
|
|
|
241
241
|
['body #1', [], []],
|
|
242
242
|
['body #a1', ['a1'], [{ byteStart: 5, byteEnd: 8 }]],
|
|
243
243
|
['#', [], []],
|
|
244
|
+
['#?', [], []],
|
|
244
245
|
['text #', [], []],
|
|
245
246
|
['text # text', [], []],
|
|
246
247
|
[
|
|
247
|
-
'body #
|
|
248
|
-
['
|
|
249
|
-
[{ byteStart: 5, byteEnd:
|
|
248
|
+
'body #thisisa64characterstring_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
|
249
|
+
['thisisa64characterstring_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'],
|
|
250
|
+
[{ byteStart: 5, byteEnd: 70 }],
|
|
250
251
|
],
|
|
251
252
|
[
|
|
252
|
-
'body #
|
|
253
|
+
'body #thisisa65characterstring_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab',
|
|
253
254
|
[],
|
|
254
255
|
[],
|
|
255
256
|
],
|
|
@@ -297,6 +298,27 @@ describe('detectFacets', () => {
|
|
|
297
298
|
{ byteStart: 17, byteEnd: 22 },
|
|
298
299
|
],
|
|
299
300
|
],
|
|
301
|
+
['this #️⃣tag should not be a tag', [], []],
|
|
302
|
+
[
|
|
303
|
+
'this ##️⃣tag should be a tag',
|
|
304
|
+
['#️⃣tag'],
|
|
305
|
+
[
|
|
306
|
+
{
|
|
307
|
+
byteStart: 5,
|
|
308
|
+
byteEnd: 16,
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
],
|
|
312
|
+
[
|
|
313
|
+
'this #t\nag should be a tag',
|
|
314
|
+
['t'],
|
|
315
|
+
[
|
|
316
|
+
{
|
|
317
|
+
byteStart: 5,
|
|
318
|
+
byteEnd: 7,
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
],
|
|
300
322
|
]
|
|
301
323
|
|
|
302
324
|
for (const [input, tags, indices] of inputs) {
|