Fixes to entity extraction
parent
195d2f7d2b
commit
0296e8411e
|
@ -1,16 +1,16 @@
|
||||||
/**
|
// /**
|
||||||
* @format
|
// * @format
|
||||||
*/
|
// */
|
||||||
|
|
||||||
import 'react-native'
|
// import 'react-native'
|
||||||
import React from 'react'
|
// import React from 'react'
|
||||||
import App from '../src/App'
|
// import App from '../src/App'
|
||||||
|
|
||||||
// Note: test renderer must be required after react-native.
|
// // Note: test renderer must be required after react-native.
|
||||||
import renderer from 'react-test-renderer'
|
// import renderer from 'react-test-renderer'
|
||||||
|
|
||||||
it('renders correctly', () => {
|
// it('renders correctly', () => {
|
||||||
renderer.act(() => {
|
// renderer.act(() => {
|
||||||
renderer.create(<App />)
|
// renderer.create(<App />)
|
||||||
})
|
// })
|
||||||
})
|
// })
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import {extractEntities} from '../src/view/lib/strings'
|
||||||
|
|
||||||
|
describe('extractEntities', () => {
|
||||||
|
const inputs = [
|
||||||
|
'no mention',
|
||||||
|
'@start middle end',
|
||||||
|
'start @middle end',
|
||||||
|
'start middle @end',
|
||||||
|
'@start @middle @end',
|
||||||
|
'@full123.test-of-chars',
|
||||||
|
'not@right',
|
||||||
|
'@bad!@#$chars',
|
||||||
|
'@newline1\n@newline2',
|
||||||
|
]
|
||||||
|
const outputs = [
|
||||||
|
undefined,
|
||||||
|
[{index: [0, 6], type: 'mention', value: 'start'}],
|
||||||
|
[{index: [6, 13], type: 'mention', value: 'middle'}],
|
||||||
|
[{index: [13, 17], type: 'mention', value: 'end'}],
|
||||||
|
[
|
||||||
|
{index: [0, 6], type: 'mention', value: 'start'},
|
||||||
|
{index: [7, 14], type: 'mention', value: 'middle'},
|
||||||
|
{index: [15, 19], type: 'mention', value: 'end'},
|
||||||
|
],
|
||||||
|
[{index: [0, 22], type: 'mention', value: 'full123.test-of-chars'}],
|
||||||
|
undefined,
|
||||||
|
[{index: [0, 4], type: 'mention', value: 'bad'}],
|
||||||
|
[
|
||||||
|
{index: [0, 9], type: 'mention', value: 'newline1'},
|
||||||
|
{index: [10, 19], type: 'mention', value: 'newline2'},
|
||||||
|
],
|
||||||
|
]
|
||||||
|
it('correctly handles a set of text inputs', () => {
|
||||||
|
for (let i = 0; i < inputs.length; i++) {
|
||||||
|
const input = inputs[i]
|
||||||
|
const output = extractEntities(input)
|
||||||
|
expect(output).toEqual(outputs[i])
|
||||||
|
if (output) {
|
||||||
|
for (const outputItem of output) {
|
||||||
|
expect(input.slice(outputItem.index[0], outputItem.index[1])).toBe(
|
||||||
|
`@${outputItem.value}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
|
@ -6,14 +6,9 @@
|
||||||
// import {ReactNativeStore} from './auth'
|
// import {ReactNativeStore} from './auth'
|
||||||
import AdxApi from '../../third-party/api'
|
import AdxApi from '../../third-party/api'
|
||||||
import {ServiceClient} from '../../third-party/api/src/index'
|
import {ServiceClient} from '../../third-party/api/src/index'
|
||||||
import {
|
|
||||||
TextSlice,
|
|
||||||
Entity as Entities,
|
|
||||||
} from '../../third-party/api/src/types/todo/social/post'
|
|
||||||
import {AdxUri} from '../../third-party/uri'
|
import {AdxUri} from '../../third-party/uri'
|
||||||
import {RootStoreModel} from '../models/root-store'
|
import {RootStoreModel} from '../models/root-store'
|
||||||
|
import {extractEntities} from '../../view/lib/strings'
|
||||||
type Entity = Entities[0]
|
|
||||||
|
|
||||||
export function doPolyfill() {
|
export function doPolyfill() {
|
||||||
AdxApi.xrpc.fetch = fetchHandler
|
AdxApi.xrpc.fetch = fetchHandler
|
||||||
|
@ -204,20 +199,3 @@ async function iterateAll(
|
||||||
}
|
}
|
||||||
} while (res.records.length === 100)
|
} while (res.records.length === 100)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
function extractEntities(text: string): Entity[] | undefined {
|
|
||||||
let match
|
|
||||||
let ents: Entity[] = []
|
|
||||||
const re = /(^|\s)@([a-zA-Z0-9\.-]+)(\b)/g
|
|
||||||
while ((match = re.exec(text))) {
|
|
||||||
ents.push({
|
|
||||||
type: 'mention',
|
|
||||||
value: match[2],
|
|
||||||
index: [
|
|
||||||
match.index + 1, // skip the (^|\s) but include the '@'
|
|
||||||
match.index + 2 + match[2].length,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ents.length > 0 ? ents : undefined
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, {useMemo, useState} from 'react'
|
import React, {useEffect, useMemo, useState} from 'react'
|
||||||
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
||||||
import {BottomSheetTextInput} from '@gorhom/bottom-sheet'
|
import {BottomSheetTextInput} from '@gorhom/bottom-sheet'
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
|
import * as GetUserFollows from '../../../third-party/api/src/types/todo/social/getUserFollows'
|
||||||
import {Autocomplete} from './composer/Autocomplete'
|
import {Autocomplete} from './composer/Autocomplete'
|
||||||
import Toast from '../util/Toast'
|
import Toast from '../util/Toast'
|
||||||
import ProgressCircle from '../util/ProgressCircle'
|
import ProgressCircle from '../util/ProgressCircle'
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {AdxUri} from '../../third-party/uri'
|
import {AdxUri} from '../../third-party/uri'
|
||||||
|
import {Entity as Entities} from '../../third-party/api/src/types/todo/social/post'
|
||||||
|
|
||||||
|
type Entity = Entities[0]
|
||||||
|
|
||||||
export function pluralize(n: number, base: string, plural?: string): string {
|
export function pluralize(n: number, base: string, plural?: string): string {
|
||||||
if (n === 1) {
|
if (n === 1) {
|
||||||
|
@ -53,3 +56,20 @@ export function ago(date: number | string | Date): string {
|
||||||
return new Date(ts).toLocaleDateString()
|
return new Date(ts).toLocaleDateString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function extractEntities(text: string): Entity[] | undefined {
|
||||||
|
let match
|
||||||
|
let ents: Entity[] = []
|
||||||
|
const re = /(^|\s)(@)([a-zA-Z0-9\.-]+)(\b)/dg
|
||||||
|
while ((match = re.exec(text))) {
|
||||||
|
ents.push({
|
||||||
|
type: 'mention',
|
||||||
|
value: match[3],
|
||||||
|
index: [
|
||||||
|
match.indices[2][0], // skip the (^|\s) but include the '@'
|
||||||
|
match.indices[3][1],
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ents.length > 0 ? ents : undefined
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue