// ========================================== // DOMAIN: ПРИЛОЖЕНИЯ // ========================================== #import "document.typ": fail #let attachment( id, title, body, subtitle: none, number: auto, outlined: true, ) = { if type(id) != str or id.trim() == "" { fail("attachment.id", "нужна непустая строка") } if type(title) not in (str, content) { fail("attachment.title", "ожидались str или content") } if type(body) not in (content, function) { fail("attachment.body", "ожидались content или function") } if subtitle != none and type(subtitle) not in (str, content) { fail("attachment.subtitle", "ожидались none, str или content") } ( kind: "attachment", id: id, title: title, subtitle: subtitle, body: body, number: number, outlined: outlined, ) } #let attachment-set(items: (), numbering: "arabic", start: 1) = { if type(items) != array { fail("attachments.items", "ожидался array") } if numbering not in ("arabic", "cyrillic", "none") { fail("attachments.numbering", "допустимы arabic, cyrillic, none") } if type(start) != int or start < 1 { fail("attachments.start", "нужно положительное целое число") } let seen = () for item in items { if type(item) != dictionary or item.at("kind", default: none) != "attachment" { fail("attachments.items", "каждый элемент должен быть attachment") } if item.id in seen { fail("attachments.items", "повторяющийся id " + repr(item.id)) } seen.push(item.id) } ( kind: "attachment-set", items: items, numbering: numbering, start: start, ) } #let validate-attachment-set(value) = { if type(value) == array { attachment-set(items: value) } else if type(value) != dictionary or value.at("kind", default: none) != "attachment-set" { fail("attachments", "ожидались array или attachment-set") } else { attachment-set( items: value.at("items", default: ()), numbering: value.at("numbering", default: "arabic"), start: value.at("start", default: 1), ) } }