How can I parse this two-level array, or is there a better alternative

Please try avoiding using markup square brackets in scripting if you continue to use scripting inside. It can add spaces in some cases. Can you share the reason you are using it? I don’t think documentation has this.

Like @quachpas said, maybe restatement really should be restatements, even though you technically can pass only one. I guess this is the same problem as document.author.

To parse array with different data structures, use type(). With array.map you can check the type and change the element’s structure.

The conditional set rule doesn’t work this way, see this.

There is also block.spacing.

#let    QGray = luma(175)
#let   QInset = 2em
#let   QScale = 1.1818em // roughly 13pt for 11pt text

#let   QAOpen = text(size: QScale, fill: QGray)[--]
#let QAIndent = -4mm  // Indent for attribution decoration

#let   QROpen = text(size: QScale, fill: QGray)[\[]
#let  QRClose = text(size: QScale, fill: QGray)[#sym.wj\]]
#let QRIndent = -2.5mm  // Indent for attribution decoration

#let   QTOpen = text(size: QScale, fill: QGray)[\(]
#let  QTClose = text(size: QScale, fill: QGray)[#sym.wj\)]
#let QTIndent = -2.5mm  // Indent for attribution decoration

#let Quote(
  label: none,
  attribution: none,
  restatement: (),
  translation: (),
  lang: none,
  body,
) = {
  if type(restatement) != array { restatement = (restatement,) }
  if type(translation) != array { translation = (translation,) }
  restatement = restatement.map(x => if type(x) != array { (lang, x) } else { x })
  block(spacing: 0em, inset: QInset, {
    set text(lang: lang) if lang != none
    body
    for (lang, restate) in restatement {
        set text(lang: lang)
      par(first-line-indent: QRIndent)[#QROpen (#lang) #restate #QRClose]
    }
    for trans in translation {
      par(first-line-indent: QTIndent)[#QTOpen #trans #QTClose]
    }
    if attribution != none {
      par(first-line-indent: QAIndent)[#QAOpen #attribution]
    }
  })
}

#Quote(
  attribution: [Synesius of Cyrene (_circa_ 370--_circa_ 413) in modernized Greek, followed by Latin restatements (1) as used by Robert Burton in _The Anatomy of Melancholy_ (1628) and matching the Latin by Thomas Naogeorgus (1559), (2) published by Claudius Morellus in a 1605 collection of Synesius's letters, and (3) by Rudolf Hercher in his 1873 collection of the letters, followed by Burton's English translation],
  restatement: (
     [restatement_in_language_of_quotation],
     ("us", ["restatement_in_other_language"]),
     ("ru", ["phonetic" transcription]),
  ),
  translation: [It is a greater offence to ſteale dead mens labours, than their clothes],
  lang: "el"
)[ἡγοῦμαι δὲ ἀσεβέστερον ἀποθανόντων λόγους κλέπτειν ἢ θοἰμάτια, ὃ καλεῖται τυμβωρυχεῖν.
]

With show rule wrapping it can be slightly simplified:

#let Quote(
  label: none,
  attribution: none,
  restatement: (),
  translation: (),
  lang: none,
  body,
) = {
  if type(restatement) != array { restatement = (restatement,) }
  if type(translation) != array { translation = (translation,) }
  restatement = restatement.map(x => if type(x) != array { (lang, x) } else { x })
  show: block.with(spacing: 0em, inset: QInset)
  set text(lang: lang) if lang != none
  body
  for (lang, restate) in restatement {
    set text(lang: lang)
    par(first-line-indent: QRIndent)[#QROpen (#lang) #restate #QRClose]
  }
  for trans in translation {
    par(first-line-indent: QTIndent)[#QTOpen #trans #QTClose]
  }
  if attribution != none {
    par(first-line-indent: QAIndent)[#QAOpen #attribution]
  }
}
1 Like