import { SourceCode } from "./SourceCode" ; import { Language } from "./lang/LanguageInterface" ; import { English } from "./lang/English" ; import { AbstractMarker } from "./AbstractMarker" ; const isCapitalized = ( text ) => { if ( ! text || text . length === 0 ) { return false ; } return /^[A-Z]/ . test ( text ) ; } ; const compareNoCaseSensitive = ( a , b ) : boolean => { return a . toLowerCase ( ) === b . toLowerCase ( ) ; } ; /**
 * abbreviation marker
 */ export class AbbrMarker implements AbstractMarker { private lang : Language ; constructor ( lang = English ) { this . lang = lang ; } param { SourceCode } sourceCode param { number } startIndex returns { string } private getWord ( sourceCode , startIndex = 0 ) { const whiteSpace = /\s/ ; const prevChar = sourceCode . read ( - 1 ) ; if ( prevChar && ! whiteSpace . test ( prevChar ) ) { return "" ; } let word = "" ; let count = startIndex ; let char = "" ; while ( ( char = sourceCode . read ( count ) ) ) { if ( whiteSpace . test ( char ) ) { break ; } word += char ; count ++ ; } return word ; } private getPrevWord ( sourceCode ) { const whiteSpace = /\s/ ; let count = - 1 ; let char = "" ; while ( ( char = sourceCode . read ( count ) ) ) { if ( ! whiteSpace . test ( char ) ) { break ; } count -- ; } while ( ( char = sourceCode . read ( count ) ) ) { if ( whiteSpace . test ( char ) ) { break ; } count -- ; } return this . getWord ( sourceCode , count + 1 ) ; } mark ( sourceCode ) { if ( sourceCode . isInContextRange ( ) ) { return ; } const currentWord = this . getWord ( sourceCode ) ; if ( currentWord . length === 0 ) { return ; } if ( /^([a-zA-Z]\.){3,}$/ . test ( currentWord ) ) { return sourceCode . markContextRange ( [ sourceCode . offset , sourceCode . offset + currentWord . length ] ) ; } const isMatchedEXCALAMATION_WORDS = this . lang . EXCALAMATION_WORDS . some ( abbr => { return compareNoCaseSensitive ( abbr , currentWord ) ; } ) ; if ( isMatchedEXCALAMATION_WORDS ) { return sourceCode . markContextRange ( [ sourceCode . offset , sourceCode . offset + currentWord . length ] ) ; } const isMatchedPREPOSITIVE_ABBREVIATIONS = this . lang . PREPOSITIVE_ABBREVIATIONS . some ( abbr => { return compareNoCaseSensitive ( abbr , currentWord ) ; } ) ; if ( isMatchedPREPOSITIVE_ABBREVIATIONS ) { return sourceCode . markContextRange ( [ sourceCode . offset , sourceCode . offset + currentWord . length ] ) ; } const isMatched = this . lang . ABBREVIATIONS . some ( abbr => { return compareNoCaseSensitive ( abbr , currentWord ) ; } ) ; const prevWord = this . getPrevWord ( sourceCode ) ; const nextWord = this . getWord ( sourceCode , currentWord . length + 1 ) ; if ( isCapitalized ( prevWord ) && /[A-Z]\./ . test ( currentWord ) && isCapitalized ( nextWord ) ) { sourceCode . markContextRange ( [ sourceCode . offset , sourceCode . offset + currentWord . length ] ) ; } else if ( isMatched && ! isCapitalized ( nextWord ) ) { sourceCode . markContextRange ( [ sourceCode . offset , sourceCode . offset + currentWord . length ] ) ; } } }