With this the extra line sometimes show up, but I have no idea yet under what circumstances precisely.
const transform_menupopup: any = this.document.getElementById('zotero-field-transform-menu')
const bbt_sentencecase_id = 'better-bibtex-transform-sentence-case'
transform_menupopup.addEventListener('popupshowing', () => {
Zotero.debug('popup showing: running')
let bbt_sentencecase: any = this.document.getElementById(bbt_sentencecase_id)
if (!bbt_sentencecase) {
bbt_sentencecase = transform_menupopup .appendChild(
this.elements.create('menuitem', {
label: 'BBT sentence-case',
id: bbt_sentencecase_id,
class: 'menuitem-non-iconic',
oncommand: () => { textTransformField.call(this.itemBoxInstance, (this.document as any).popupNode) },
})
)
}
bbt_sentencecase.disabled = !canTextTransformField.call(this.itemBoxInstance, (this.document as any).popupNode)
})
I'd be fine with just offering the BBT sentence-caser to Zotero to circumvent this problem. It's not big (90 LoC), but it needs XRegExp. One thing that can be done in just a few LoC is exempt <span class="nocase"> parts from sentencecaseing, but the BBT sentencecaser does some work to properly treat words that have internal markup as a single word. If Zotero does npm modules (I think it does?) there wouldn't even need to be much of a PR, because this would do it:
import { toSentenceCase } from '@retorquere/bibtex-parser'
function sentenceCase(text) {
let sentencecased = toSentenceCase(text)
// restore protected parts from original
text.replace(/<span class="nocase">.*?<\/span>|<nc>.*?<\/nc>/gi, (match: string, offset: number) => {
sentencecased = sentencecased.substr(0, offset) + match + sentencecased.substr(offset + match.length)
return match
})
return sentencecased
}
but that would require tree-shaking to get rid of the bibtex parser. And I could well imagine Zotero wouldn't like being dependent on modules out its control. So a PR would be a fine route for me.
Another option would be to monkey-patch itemBox.textTransformString(val, 'sentence'), but I'm not so keen on replacing stock behavior these days.