@@ -81,18 +81,42 @@ export function parseSingle(citation: string, strict: boolean = false): Citation
81
81
// they are simply square brackets. Additionally, split the citation along delimiters.
82
82
let _citation = citation . substr ( 1 , citation . length - 2 ) . split ( ';' )
83
83
84
+ let invalidPrefixes : string [ ] = [ ]
85
+
84
86
// Now iterate over all citations the user passed in to return them as an array.
85
87
for ( let c of _citation ) {
86
88
// It could be that the user just ended his/her citation with a ;
87
89
if ( c === '' ) continue
88
90
89
91
// Make sure there is exactly one @ available.
90
- if ( ! validateCitationPart ( c ) ) throw new Error ( `No key or multiple keys Found - Invalid citation passed: ${ c } .` )
92
+ if ( ! validateCitationPart ( c ) ) {
93
+ // If the validator fails, this means that there's no @ or multiple @,
94
+ // and hence no valid citation key in there. This means that the user has
95
+ // written something along the lines of [as we can see here; further
96
+ // @citekey 1234; @citekey4321] or [see the corresponding mails
97
+ // hello@example .com and [email protected] ; further @citekey1234].
98
+ // --> treat it as a part of the prefix for the next citation part.
99
+ invalidPrefixes . push ( c )
100
+ continue
101
+ }
91
102
92
- // The Prefix is defined as everything before the citation key, so the first index of
93
- // the split array will contain the Prefix (If @ is the first character, the string will
94
- // be empty).
95
- let prefix = c . split ( '@' ) [ 0 ] . trim ( )
103
+ // The Prefix is defined as everything before the citation key, so the
104
+ // first index of the split array will contain the Prefix (If @ is the
105
+ // first character, the string will be empty). Make sure to add possible
106
+ // invalid prefixes from before
107
+ let prefix = ''
108
+ if ( invalidPrefixes . length === 1 ) {
109
+ prefix = invalidPrefixes + ';'
110
+ }
111
+ else if ( invalidPrefixes . length > 1 ) {
112
+ prefix = invalidPrefixes . join ( ';' )
113
+ }
114
+
115
+ prefix += c . split ( '@' ) [ 0 ] // Add the actual prefix
116
+ prefix = prefix . trim ( ) // Trim whitespaces
117
+
118
+ // Reset the additional prefixes here.
119
+ invalidPrefixes = [ ]
96
120
97
121
// Next, the user can decide to omit the author from the citation by prepending the
98
122
// @-character with a minus (-). We cannot look for the end of the prefix because
@@ -106,18 +130,21 @@ export function parseSingle(citation: string, strict: boolean = false): Citation
106
130
107
131
// Now we need to extract the citation key. We'll be reusing the citation
108
132
// validator regular expression. But as the secondHalf also contains the
109
- // suffix, locator, etc., we have to first cut it down. Therefore, we'll
110
- // assume a comma to separate the citekey from the rest of the suffix (or
111
- // extract everything, if there is no comma in there.)
133
+ // suffix, locator, etc., we have to first cut it down. The citation key
134
+ // can either be terminated with a comma or with a space.
112
135
let commaIndex : number | undefined = c . split ( '@' ) [ 1 ] . indexOf ( ',' ) + 1
136
+ // If the commaIndex is 0, this means there was no comma - check for space
137
+ if ( commaIndex === 0 ) commaIndex = c . split ( '@' ) [ 1 ] . indexOf ( ' ' ) + 1
113
138
// Pass undefined to extract everything
114
139
if ( commaIndex <= 0 ) commaIndex = undefined
140
+
141
+ // Now extract the key
115
142
let citationKeyPart = c . substr ( c . indexOf ( '@' ) , commaIndex )
116
143
let extractedKey : RegExpExecArray | null = null
117
144
if ( strict ) {
118
- extractedKey = looseCitekeyValidatorRE . exec ( citationKeyPart )
119
- } else {
120
145
extractedKey = strictCitekeyValidatorRE . exec ( citationKeyPart )
146
+ } else {
147
+ extractedKey = looseCitekeyValidatorRE . exec ( citationKeyPart )
121
148
}
122
149
123
150
// If the match has not been found, abort
@@ -128,7 +155,7 @@ export function parseSingle(citation: string, strict: boolean = false): Citation
128
155
129
156
// The final two things that could possibly still be in the citation are a
130
157
// locator and a suffix. Let us first extract everything after the key.
131
- let afterKey = c . split ( '@' ) [ 1 ] . substr ( extractedKey [ 0 ] . length + 1 ) . trim ( )
158
+ let afterKey = c . split ( '@' ) [ 1 ] . substr ( extractedKey [ 1 ] . length ) . trim ( )
132
159
133
160
// The logic to get the locator is extremely difficult, as the locator
134
161
// mainly is written in natural language. We'll offload the work to
@@ -146,6 +173,12 @@ export function parseSingle(citation: string, strict: boolean = false): Citation
146
173
} )
147
174
}
148
175
176
+ // Indicate that no citation has been found, which is a good indicator
177
+ // that there is no valid citation (even excluding the invalid prefixes)
178
+ if ( returnCitations . length === 0 && _citation . length > 0 ) {
179
+ throw new Error ( `Invalid citation passed: ${ citation } ` )
180
+ }
181
+
149
182
// After everything has run, return all citations found.
150
183
return returnCitations
151
184
}
0 commit comments