diff --git a/src/actions/__tests__/splitSentences.ts b/src/actions/__tests__/splitSentences.ts index a04e558020..0e71dad95e 100644 --- a/src/actions/__tests__/splitSentences.ts +++ b/src/actions/__tests__/splitSentences.ts @@ -297,8 +297,8 @@ describe('abbreviations', () => { const exported = splitThought(value) expect(exported).toBe(`- ${HOME_TOKEN} - - One. - - Two ( U.N.)`) + - One. Two + - U.N.`) }) it('split thought as expected if the dot comes from an abbreviation followed by empty spaces and a quotation mark', () => { @@ -647,3 +647,31 @@ describe('complicated cases', () => { - IPv4: 11.11.11.111`) }) }) + +describe('parenthetical content', () => { + it('splits thought with parenthetical content at the end into main thought and subthought', () => { + const value = 'This is a thought (and a subthought)' + const exported = splitThought(value) + + expect(exported).toBe(`- ${HOME_TOKEN} + - This is a thought + - and a subthought`) + }) + + it('splits thought with parenthetical content that ends with a period', () => { + const value = 'This is a thought (and a subthought).' + const exported = splitThought(value) + + expect(exported).toBe(`- ${HOME_TOKEN} + - This is a thought + - and a subthought`) + }) + + it('does not split when parentheses are not at the end', () => { + const value = 'This (has parentheses) in the middle' + const exported = splitThought(value) + + expect(exported).toBe(`- ${HOME_TOKEN} + - This (has parentheses) in the middle`) + }) +}) diff --git a/src/actions/splitSentences.ts b/src/actions/splitSentences.ts index 7ae7ff1bce..ae318ed615 100644 --- a/src/actions/splitSentences.ts +++ b/src/actions/splitSentences.ts @@ -30,12 +30,14 @@ const splitSentences = (state: State) => { const reducers = [ editThought({ oldValue: value, - newValue: firstSentence, + newValue: firstSentence.value, path: simplifyPath(state, cursor), rankInContext: rank, }), - ...otherSentences.map(sentence => newThought({ value: sentence })), - setCursor({ path: cursor, offset: getTextContentFromHTML(firstSentence).length }), + ...otherSentences.map(sentence => + newThought({ value: sentence.value, insertNewSubthought: sentence.insertNewSubThought }), + ), + setCursor({ path: cursor, offset: getTextContentFromHTML(firstSentence.value).length }), editableRender, ] diff --git a/src/util/splitSentence.ts b/src/util/splitSentence.ts index 7a83293e8b..f2339a73c9 100644 --- a/src/util/splitSentence.ts +++ b/src/util/splitSentence.ts @@ -47,10 +47,26 @@ function isUrl(str1: string, s: string) { return urlPattern.test(combinedSentence) } +interface SplitResult { + value: string + insertNewSubThought?: boolean +} + /** * Splits given value by special characters. */ -const splitSentence = (value: string): string[] => { +const splitSentence = (value: string): SplitResult[] => { + // Check for parenthetical content at the end of the thought first + // pattern : ), ). + // "This is a thought (and a subthought)" -> "-This is a thought -and a subthought" + const parentheticalMatch = value.match(/^(.*?)\s*\((.*?)\)\.?$/) + if (parentheticalMatch) { + const [_, mainThought, subThought] = parentheticalMatch + return [{ value: mainThought.trim() }, { value: subThought.trim(), insertNewSubThought: true }].filter( + s => s.value !== '', + ) + } + // pattern1, single symbol: . ; ! ? // pattern2, multiple symbols: ?! !!! ... const mainSplitRegex = /[.;!?]+/g @@ -70,6 +86,7 @@ const splitSentence = (value: string): string[] => { .split(/,|and/i) .map(s => s.trim()) .filter(s => s !== '') + .map(value => ({ value })) /** * When the setences can be split, it has multiple situations. @@ -133,10 +150,10 @@ const splitSentence = (value: string): string[] => { .replace(/,/g, `${SEPARATOR_TOKEN}`) .split(SEPARATOR_TOKEN) .filter(s => /\S+/.test(s)) - .map(s => s.trim()) + .map(s => ({ value: s.trim() })) } - return res.map(s => s.trim()) + return res.map(s => ({ value: s.trim() })) } export default splitSentence