|
120 | 120 |
|
121 | 121 | // `update` method for this richer-counter |
122 | 122 | // only support array of integers as counter value |
123 | | - let update(counter-value) = [ |
124 | | - #metadata(( |
125 | | - kind: "richer-counter:update", |
126 | | - identifier: identifier, |
127 | | - value: counter-value, |
128 | | - )) |
129 | | - #label("richer-counter:update:" + identifier) |
130 | | - ] |
| 123 | + let update(counter-value) = { |
| 124 | + assert( |
| 125 | + type(counter-value) == array and counter-value.all(v => type(v) == int), |
| 126 | + message: "Counter value for '" + identifier + "' must be an array of integers, e.g. (1, 2).", |
| 127 | + ) |
| 128 | + [ |
| 129 | + #metadata(( |
| 130 | + kind: "richer-counter:update", |
| 131 | + identifier: identifier, |
| 132 | + value: counter-value, |
| 133 | + )) |
| 134 | + #label("richer-counter:update:" + identifier) |
| 135 | + ] |
| 136 | + } |
131 | 137 |
|
132 | 138 | // find updates of own partial (!) counter in certain range |
133 | 139 | let updates-during(after-key, before-key) = { |
|
315 | 321 | } |
316 | 322 |
|
317 | 323 | /// Useful functions for the frame. |
| 324 | + // Helper: check whether a title value is non-empty (works for both str and content) |
| 325 | + let has-nonempty-title(title) = (type(title) == str and title != "") or (type(title) == content and title != [] and title != [#""]) |
318 | 326 | let get-prefix(get-loc, number: auto, supplement: auto) = [#if supplement == auto { supplement-i18n } else { |
319 | 327 | supplement |
320 | | - } #if number == auto { display-number(get-loc: get-loc)() } else { number }] |
321 | | - let get-full-title(prefix, title) = [#prefix#{ if title != "" [ (#title)] }] |
| 328 | + } #if number == auto { display-number(get-loc: get-loc)() } else if type(number) == array { |
| 329 | + context std.numbering(get-numbering(get-loc()), ..number) |
| 330 | + } else { number }] |
| 331 | + let get-full-title(prefix, title) = [#prefix#{ |
| 332 | + if has-nonempty-title(title) [ (#title)] |
| 333 | + }] |
322 | 334 | /// Frame with the counter. |
323 | 335 | let frame( |
324 | 336 | title: "", |
|
330 | 342 | get-full-title: get-full-title, |
331 | 343 | ..args, |
332 | 344 | body, |
333 | | - ) = figure( |
334 | | - kind: identifier, |
335 | | - supplement: if supplement == auto { supplement-i18n } else { supplement }, |
336 | | - caption: title, |
337 | | - outlined: outlined, |
338 | | - numbering: if number == auto { numbering } else { (..args) => (kind: "static", value: number) }, |
339 | | - { |
340 | | - [#metadata(( |
341 | | - identifier: identifier, |
342 | | - number: number, |
| 345 | + ) = { |
| 346 | + // Support positional title syntax: #theorem[Title][Body] |
| 347 | + let actual-title = if args.pos().len() > 0 and title == "" { |
| 348 | + args.pos().first() |
| 349 | + } else { |
| 350 | + title |
| 351 | + } |
| 352 | + // For array numbers, emit counter update BEFORE the figure so that |
| 353 | + // theorion-display-number (which reads at el.location()) sees the updated value. |
| 354 | + if type(number) == array and number.len() > 0 { |
| 355 | + let target = number.slice(0, -1) + (number.last() - 1,) |
| 356 | + (frame-counter.update)(target) |
| 357 | + } |
| 358 | + figure( |
| 359 | + kind: identifier, |
| 360 | + supplement: if supplement == auto { supplement-i18n } else { supplement }, |
| 361 | + caption: actual-title, |
| 362 | + outlined: outlined, |
| 363 | + numbering: if number == auto or type(number) == array { |
| 364 | + numbering |
| 365 | + } else { |
| 366 | + (..fig-args) => (kind: "static", value: number) |
| 367 | + }, |
| 368 | + { |
| 369 | + [#metadata(( |
| 370 | + identifier: identifier, |
| 371 | + number: number, |
| 372 | + supplement: supplement, |
| 373 | + supplement-map: supplement-map, |
| 374 | + supplement-i18n: supplement-i18n, |
| 375 | + kind: identifier, |
| 376 | + counter: frame-counter, |
| 377 | + title: actual-title, |
| 378 | + numbering: numbering, |
| 379 | + outlined: outlined, |
| 380 | + get-prefix: get-prefix, |
| 381 | + get-full-title: get-full-title, |
| 382 | + render: render, |
| 383 | + args: args, |
| 384 | + body: body, |
| 385 | + )) <theorion-frame-metadata>] |
| 386 | + let prefix = get-prefix( |
| 387 | + here, |
| 388 | + number: if type(number) == array { auto } else { number }, |
343 | 389 | supplement: supplement, |
344 | | - supplement-map: supplement-map, |
345 | | - supplement-i18n: supplement-i18n, |
346 | | - kind: identifier, |
347 | | - counter: frame-counter, |
348 | | - title: title, |
349 | | - numbering: numbering, |
350 | | - outlined: outlined, |
351 | | - get-prefix: get-prefix, |
352 | | - get-full-title: get-full-title, |
353 | | - render: render, |
354 | | - args: args, |
355 | | - body: body, |
356 | | - )) <theorion-frame-metadata>] |
357 | | - let prefix = get-prefix(here, number: number, supplement: supplement) |
358 | | - render( |
359 | | - prefix: prefix, |
360 | | - title: title, |
361 | | - full-title: get-full-title(prefix, title), |
362 | | - ..args, |
363 | | - body, |
364 | | - ) |
365 | | - // Update the counter. |
366 | | - if numbering != none and number == auto { |
367 | | - (frame-counter.step)() |
368 | | - } |
369 | | - }, |
370 | | - ) |
| 390 | + ) |
| 391 | + render( |
| 392 | + prefix: prefix, |
| 393 | + title: actual-title, |
| 394 | + full-title: get-full-title(prefix, actual-title), |
| 395 | + ..args.named(), |
| 396 | + body, |
| 397 | + ) |
| 398 | + // Update the counter. |
| 399 | + if numbering != none and (number == auto or type(number) == array) { |
| 400 | + (frame-counter.step)() |
| 401 | + } |
| 402 | + }, |
| 403 | + ) |
| 404 | + } |
371 | 405 | /// Frame without the counter. |
372 | 406 | let frame-box = frame.with( |
373 | 407 | numbering: none, |
|
406 | 440 | let el = it.element |
407 | 441 | if el != none and el.func() == figure and el.kind == identifier { |
408 | 442 | link(el.location(), { |
409 | | - let supplement = if it.supplement == auto { el.supplement } else { it.supplement } |
410 | | - if supplement != none { |
411 | | - supplement |
412 | | - " " |
| 443 | + if it.supplement == [-] { |
| 444 | + // @label[-]: number only, no supplement |
| 445 | + context theorion-display-number(el) |
| 446 | + } else if it.supplement == [!!] { |
| 447 | + // @label[!!]: supplement + number + title |
| 448 | + let supplement = el.supplement |
| 449 | + if supplement != none { |
| 450 | + supplement |
| 451 | + " " |
| 452 | + } |
| 453 | + context theorion-display-number(el) |
| 454 | + context { |
| 455 | + let title = el.caption.body |
| 456 | + if has-nonempty-title(title) [ (#title)] |
| 457 | + } |
| 458 | + } else { |
| 459 | + let supplement = if it.supplement == auto { el.supplement } else { it.supplement } |
| 460 | + if supplement != none { |
| 461 | + supplement |
| 462 | + " " |
| 463 | + } |
| 464 | + context theorion-display-number(el) |
413 | 465 | } |
414 | | - context theorion-display-number(el) |
415 | 466 | }) |
416 | 467 | } else { |
417 | 468 | it |
|
0 commit comments