Skip to content

Commit 9b4585c

Browse files
committed
feat: move most smartQuote logic from dispatcher to smartQuotes
1 parent cffc4d6 commit 9b4585c

File tree

2 files changed

+43
-37
lines changed

2 files changed

+43
-37
lines changed

src/dispatcher.js

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import config from './config.js'
66
import Keyboard from './keyboard.js'
77
import {closest} from './util/dom.js'
88
import {replaceLast, endsWithSingleSpace} from './util/string.js'
9-
import {shouldApplySmartQuotes, isQuote, isOpeningQuote, isClosingQuote} from './smartQuotes.js'
9+
import {applySmartQuotes, shouldApplySmartQuotes} from './smartQuotes.js'
1010

1111
/**
1212
* The Dispatcher module is responsible for dealing with events and their handlers.
@@ -147,36 +147,14 @@ export default class Dispatcher {
147147
if (!block) return
148148

149149
const target = evt.target
150-
const currentChar = evt.data
151-
152-
153-
if (target.isContentEditable && shouldApplySmartQuotes(config)) {
154-
if (isQuote(currentChar)) {
155-
const selection = this.selectionWatcher.getFreshSelection()
156-
const wholeText = selection.range.startContainer.wholeText
157-
// const firstPart = selection.range.startContainer.textContent
158-
const offset = selection.range.startOffset
159-
if (isClosingQuote([...wholeText], offset - 2)) {
160-
const textArr = [...target.innerText]
161-
const index = offset - 1
162-
if (index >= 0 && index < textArr.length) {
163-
textArr[index] = '»'
164-
target.innerText = textArr.join('')
165-
}
166-
this.editable.createCursorAtCharacterOffset({element: block, offset})
167-
}
168-
169-
if (isOpeningQuote([...wholeText], offset - 2)) {
170-
const textArr = [...target.innerText]
171-
const index = offset - 1
172-
if (index >= 0 && index < textArr.length) {
173-
textArr[index] = '«'
174-
target.innerText = textArr.join('')
175-
}
176-
this.editable.createCursorAtCharacterOffset({element: block, offset})
177-
}
178-
}
179150

151+
if (shouldApplySmartQuotes(config, target)) {
152+
const currentChar = evt.data
153+
const selection = this.selectionWatcher.getFreshSelection()
154+
const offset = selection.range.startOffset
155+
const wholeText = [...target.innerText]
156+
const resetCursor = () => this.editable.createCursorAtCharacterOffset({element: block, offset})
157+
applySmartQuotes(config, currentChar, wholeText, offset, target, resetCursor)
180158
}
181159
this.notify('change', block)
182160
})

src/smartQuotes.js

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,43 @@
11
const isValidQuotePairConfig = (quotePair) => Array.isArray(quotePair) && quotePair.length === 2
22

3-
export const shouldApplySmartQuotes = (config) => {
3+
export const shouldApplySmartQuotes = (config, target) => {
44
const {smartQuotes, quotes, singleQuotes} = config
5-
return !!smartQuotes && isValidQuotePairConfig(quotes) && isValidQuotePairConfig(singleQuotes)
5+
return !!smartQuotes && isValidQuotePairConfig(quotes) && isValidQuotePairConfig(singleQuotes) && target.isContentEditable
66
}
77

8-
export const isQuote = (char) => /^['«»"]$/.test(char)
9-
export const isDoubleQuote = (char) => /^[«»"]$/.test(char)
10-
export const isSingleQuote = (char) => /^[']$/.test(char)
8+
// export const isQuote = (char) => /^[‘’‹›‚'«»"“”„]$/.test(char)
9+
const isDoubleQuote = (char) => /^[«»"]$/.test(char)
10+
const isSingleQuote = (char) => /^[']$/.test(char)
1111

1212
// Test: '>', ' ', no space & all kinds of dashes dash
13-
export const isOpeningQuote = (text, indexCharBefore) => indexCharBefore < 0 || /\s|[>\-]/.test(text[indexCharBefore])
13+
const isOpeningQuote = (text, indexCharBefore) => indexCharBefore < 0 || /\s|[>\-]/.test(text[indexCharBefore])
14+
const isClosingQuote = (text, indexCharBefore) => text[indexCharBefore] !== ' '
1415

15-
export const isClosingQuote = (text, indexCharBefore) => text[indexCharBefore] !== ' '
16+
const applySmartQuote = (textArr, index, target, quoteType) => {
17+
if (index >= 0 && index < textArr.length) {
18+
textArr[index] = quoteType
19+
target.innerText = textArr.join('')
20+
}
21+
}
22+
23+
export const applySmartQuotes = (config, char, wholeText, offset, target, resetCursor) => {
24+
const isCharSingleQuote = isSingleQuote(char)
25+
const isCharDoubleQuote = isDoubleQuote(char)
26+
27+
if (!isCharDoubleQuote && !isCharSingleQuote) {
28+
return
29+
}
30+
31+
const {quotes, singleQuotes} = config
32+
if (isClosingQuote(wholeText, offset - 2)) {
33+
const closingQuote = isCharSingleQuote ? singleQuotes[1] : quotes[1]
34+
applySmartQuote(wholeText, offset - 1, target, closingQuote)
35+
}
36+
37+
if (isOpeningQuote(wholeText, offset - 2)) {
38+
const openingQuote = isCharSingleQuote ? singleQuotes[0] : quotes[0]
39+
applySmartQuote(wholeText, offset - 1, target, openingQuote)
40+
}
41+
42+
resetCursor()
43+
}

0 commit comments

Comments
 (0)