├── .gitignore ├── .travis.yml ├── ACM-Reference-Format.bst ├── CITATION.cff ├── Makefile ├── README.md ├── acm-sig-proceedings.csl ├── acmart.cls ├── adjust-for-html.jq ├── html.yaml ├── infrastructure-agnostic-hypertext.md ├── interactions.yaml ├── latex.yaml ├── levels-of-data-modeling.tikz ├── metadata.yaml ├── package.json ├── poster.png ├── poster.svg ├── references.html ├── short-version ├── .gitignore ├── ACM-Reference-Format.bst ├── Makefile ├── acmart.cls ├── an-infrastructure-agnostic-model-of-hypertext.md ├── latex.yaml └── metadata.yaml ├── template.html ├── template.tex ├── this-articles-transclusion.tikz ├── tikz2svg.sh ├── wcite.json └── wcite.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.bbl 3 | *.blg 4 | *.log 5 | *.tex 6 | !template.tex 7 | 8 | node_modules/ 9 | 10 | html/ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r # implies pandoc and LaTeX 2 | 3 | before_install: 4 | - sudo apt-get install jq pdf2svg 5 | - tlmgr install totpages ncctools cmap cm-super standalone 6 | 7 | install: 8 | - npm install 9 | - git clone https://github.com/jakobib/hypertext2019.git html 10 | 11 | script: 12 | - make 13 | - make -C short-version 14 | -------------------------------------------------------------------------------- /ACM-Reference-Format.bst: -------------------------------------------------------------------------------- 1 | %%% -*-BibTeX-*- 2 | %%% ==================================================================== 3 | %%% @BibTeX-style-file{ 4 | %%% author = "Nelson H. F. Beebe, Boris Veytsman and Gerald Murray", 5 | %%% version = "2.1", 6 | %%% date = "14 June 2017", 7 | %%% filename = "ACM-Reference-Format.bst", 8 | %%% email = "borisv@lk.net, boris@varphi.com", 9 | %%% codetable = "ISO/ASCII", 10 | %%% keywords = "ACM Transactions bibliography style; BibTeX", 11 | %%% license = "public domain", 12 | %%% supported = "yes", 13 | %%% abstract = "", 14 | %%% } 15 | %%% ==================================================================== 16 | 17 | %%% Revision history: see source in git 18 | 19 | ENTRY 20 | { address 21 | advisor 22 | archiveprefix 23 | author 24 | booktitle 25 | chapter 26 | city 27 | date 28 | edition 29 | editor 30 | eprint 31 | eprinttype 32 | eprintclass 33 | howpublished 34 | institution 35 | journal 36 | key 37 | month 38 | note 39 | number 40 | organization 41 | pages 42 | primaryclass 43 | publisher 44 | school 45 | series 46 | title 47 | type 48 | volume 49 | year 50 | % New keys recognized 51 | issue % UTAH: used in, e.g., ACM SIGSAM Bulletin and ACM Communications in Computer Algebra 52 | articleno 53 | eid 54 | day % UTAH: needed for newspapers, weeklies, bi-weeklies 55 | doi % UTAH 56 | url % UTAH 57 | bookpages % UTAH 58 | numpages 59 | lastaccessed % UTAH: used only for @Misc{...} 60 | coden % UTAH 61 | isbn % UTAH 62 | isbn-13 % UTAH 63 | issn % UTAH 64 | lccn % UTAH 65 | } 66 | {} 67 | { label.year extra.label sort.year sort.label basic.label.year} 68 | 69 | INTEGERS { output.state before.all mid.sentence after.sentence after.block } 70 | 71 | INTEGERS { show-isbn-10-and-13 } % initialized below in begin.bib 72 | 73 | INTEGERS { nameptr namesleft numnames } 74 | 75 | INTEGERS { multiresult } 76 | 77 | INTEGERS { len } 78 | 79 | INTEGERS { last.extra.num } 80 | 81 | STRINGS { s t t.org u } 82 | 83 | STRINGS { last.label next.extra } 84 | 85 | STRINGS { p1 p2 p3 page.count } 86 | 87 | 88 | FUNCTION { not } 89 | { 90 | { #0 } 91 | { #1 } 92 | if$ 93 | } 94 | 95 | FUNCTION { and } 96 | { 97 | 'skip$ 98 | { pop$ #0 } 99 | if$ 100 | } 101 | 102 | FUNCTION { or } 103 | { 104 | { pop$ #1 } 105 | 'skip$ 106 | if$ 107 | } 108 | 109 | 110 | FUNCTION { dump.stack.1 } 111 | { 112 | duplicate$ "STACK[top] = [" swap$ * "]" * warning$ 113 | } 114 | 115 | FUNCTION { dump.stack.2 } 116 | { 117 | duplicate$ "STACK[top ] = [" swap$ * "]" * warning$ 118 | swap$ 119 | duplicate$ "STACK[top-1] = [" swap$ * "]" * warning$ 120 | swap$ 121 | } 122 | 123 | FUNCTION { empty.or.unknown } 124 | { 125 | %% Examine the top stack entry, and push 1 if it is empty, or 126 | %% consists only of whitespace, or is a string beginning with two 127 | %% queries (??), and otherwise, push 0. 128 | %% 129 | %% This function provides a replacement for empty$, with the 130 | %% convenient feature that unknown values marked by two leading 131 | %% queries are treated the same as missing values, and thus, do not 132 | %% appear in the output .bbl file, and yet, their presence in .bib 133 | %% file(s) serves to mark values which are temporarily missing, but 134 | %% are expected to be filled in eventually once more data is 135 | %% obtained. The TeX User Group and BibNet bibliography archives 136 | %% make extensive use of this practice. 137 | %% 138 | %% An empty string cannot serve the same purpose, because just as in 139 | %% statistics data processing, an unknown value is not the same as an 140 | %% empty value. 141 | %% 142 | %% At entry: stack = ... top:[string] 143 | %% At exit: stack = ... top:[0 or 1] 144 | 145 | duplicate$ empty$ 146 | { pop$ #1 } 147 | { #1 #2 substring$ "??" = } 148 | if$ 149 | } 150 | 151 | FUNCTION { writeln } 152 | { 153 | %% In BibTeX style files, the sequences 154 | %% 155 | %% ... "one" "two" output 156 | %% ... "one" "two" output.xxx 157 | %% 158 | %% ship "one" to the output file, possibly following by punctuation, 159 | %% leaving the stack with 160 | %% 161 | %% ... "two" 162 | %% 163 | %% There is thus a one-string lag in output processing that must be 164 | %% carefully handled to avoid duplicating a string in the output 165 | %% file. Unless otherwise noted, all output.xxx functions leave 166 | %% just one new string on the stack, and that model should be born 167 | %% in mind when reading or writing function code. 168 | %% 169 | %% BibTeX's asynchronous buffering of output from strings from the 170 | %% stack is confusing because newline$ bypasses the buffer. It 171 | %% would have been so much easier for newline to be a character 172 | %% rather than a state of the output-in-progress. 173 | %% 174 | %% The documentation in btxhak.dvi is WRONG: it says 175 | %% 176 | %% newline$ Writes onto the bbl file what's accumulated in the 177 | %% output buffer. It writes a blank line if and only 178 | %% if the output buffer is empty. Since write$ does 179 | %% reasonable line breaking, you should use this 180 | %% function only when you want a blank line or an 181 | %% explicit line break. 182 | %% 183 | %% write$ Pops the top (string) literal and writes it on the 184 | %% output buffer (which will result in stuff being 185 | %% written onto the bbl file when the buffer fills 186 | %% up). 187 | %% 188 | %% Examination of the BibTeX source code shows that write$ does 189 | %% indeed behave as claimed, but newline$ sends a newline character 190 | %% directly to the output file, leaving the stack unchanged. The 191 | %% first line "Writes onto ... buffer." is therefore wrong. 192 | %% 193 | %% The original BibTeX style files almost always use "write$ newline$" 194 | %% in that order, so it makes sense to hide that pair in a private 195 | %% function like this one, named after a statement in Pascal, 196 | %% the programming language embedded in the BibTeX Web program. 197 | 198 | write$ % output top-of-stack string 199 | newline$ % immediate write of newline (not via stack) 200 | } 201 | 202 | FUNCTION { init.state.consts } 203 | { 204 | #0 'before.all := 205 | #1 'mid.sentence := 206 | #2 'after.sentence := 207 | #3 'after.block := 208 | } 209 | 210 | FUNCTION { output.nonnull } 211 | { % Stack in: ... R S T Stack out: ... R T File out: S 212 | 's := 213 | output.state mid.sentence = 214 | { 215 | ", " * write$ 216 | } 217 | { 218 | output.state after.block = 219 | { 220 | add.period$ writeln 221 | "\newblock " write$ 222 | } 223 | { 224 | output.state before.all = 225 | { 226 | write$ 227 | } 228 | { 229 | add.period$ " " * write$ 230 | } 231 | if$ 232 | } 233 | if$ 234 | mid.sentence 'output.state := 235 | } 236 | if$ 237 | s 238 | } 239 | 240 | FUNCTION { output.nonnull.dot.space } 241 | { % Stack in: ... R S T Stack out: ... R T File out: S 242 | 's := 243 | output.state mid.sentence = % { ". " * write$ } 244 | { 245 | ". " * write$ 246 | } 247 | { 248 | output.state after.block = 249 | { 250 | add.period$ writeln "\newblock " write$ 251 | } 252 | { 253 | output.state before.all = 254 | { 255 | write$ 256 | } 257 | { 258 | add.period$ " " * write$ 259 | } 260 | if$ 261 | } 262 | if$ 263 | mid.sentence 'output.state := 264 | } 265 | if$ 266 | s 267 | } 268 | 269 | FUNCTION { output.nonnull.remove } 270 | { % Stack in: ... R S T Stack out: ... R T File out: S 271 | 's := 272 | output.state mid.sentence = 273 | { 274 | " " * write$ 275 | } 276 | { 277 | output.state after.block = 278 | { 279 | add.period$ writeln "\newblock " write$ 280 | } 281 | { 282 | output.state before.all = 283 | { 284 | write$ 285 | } 286 | { 287 | add.period$ " " * write$ 288 | } 289 | if$ 290 | } 291 | if$ 292 | mid.sentence 'output.state := 293 | } 294 | if$ 295 | s 296 | } 297 | 298 | FUNCTION { output.nonnull.removenospace } 299 | { % Stack in: ... R S T Stack out: ... R T File out: S 300 | 's := 301 | output.state mid.sentence = 302 | { 303 | "" * write$ 304 | } 305 | { 306 | output.state after.block = 307 | { 308 | add.period$ writeln "\newblock " write$ 309 | } 310 | { 311 | output.state before.all = 312 | { 313 | write$ 314 | } 315 | { 316 | add.period$ " " * write$ 317 | } 318 | if$ 319 | } 320 | if$ 321 | mid.sentence 'output.state := 322 | } 323 | if$ 324 | s 325 | } 326 | 327 | FUNCTION { output } 328 | { % discard top token if empty, else like output.nonnull 329 | duplicate$ empty.or.unknown 330 | 'pop$ 331 | 'output.nonnull 332 | if$ 333 | } 334 | 335 | FUNCTION { output.dot.space } 336 | { % discard top token if empty, else like output.nonnull.dot.space 337 | duplicate$ empty.or.unknown 338 | 'pop$ 339 | 'output.nonnull.dot.space 340 | if$ 341 | } 342 | 343 | FUNCTION { output.removenospace } 344 | { % discard top token if empty, else like output.nonnull.removenospace 345 | duplicate$ empty.or.unknown 346 | 'pop$ 347 | 'output.nonnull.removenospace 348 | if$ 349 | } 350 | 351 | FUNCTION { output.check } 352 | { % like output, but warn if key name on top-of-stack is not set 353 | 't := 354 | duplicate$ empty.or.unknown 355 | { pop$ "empty " t * " in " * cite$ * warning$ } 356 | 'output.nonnull 357 | if$ 358 | } 359 | 360 | FUNCTION { bibinfo.output.check } 361 | { % like output.check, adding bibinfo field 362 | 't := 363 | duplicate$ empty.or.unknown 364 | { pop$ "empty " t * " in " * cite$ * warning$ } 365 | { "\bibinfo{" t "}{" * * swap$ * "}" * 366 | output.nonnull } 367 | if$ 368 | } 369 | 370 | FUNCTION { output.check.dot.space } 371 | { % like output.dot.space, but warn if key name on top-of-stack is not set 372 | 't := 373 | duplicate$ empty.or.unknown 374 | { pop$ "empty " t * " in " * cite$ * warning$ } 375 | 'output.nonnull.dot.space 376 | if$ 377 | } 378 | 379 | FUNCTION { fin.block } 380 | { % functionally, but not logically, identical to fin.entry 381 | add.period$ 382 | writeln 383 | } 384 | 385 | FUNCTION { fin.entry } 386 | { 387 | add.period$ 388 | writeln 389 | } 390 | 391 | FUNCTION { new.sentence } 392 | { % update sentence state, with neither output nor stack change 393 | output.state after.block = 394 | 'skip$ 395 | { 396 | output.state before.all = 397 | 'skip$ 398 | { after.sentence 'output.state := } 399 | if$ 400 | } 401 | if$ 402 | } 403 | 404 | FUNCTION { fin.sentence } 405 | { 406 | add.period$ 407 | write$ 408 | new.sentence 409 | "" 410 | } 411 | 412 | FUNCTION { new.block } 413 | { 414 | output.state before.all = 415 | 'skip$ 416 | { after.block 'output.state := } 417 | if$ 418 | } 419 | 420 | FUNCTION { output.coden } % UTAH 421 | { % output non-empty CODEN as one-line sentence (stack untouched) 422 | coden empty.or.unknown 423 | { } 424 | { "\showCODEN{" coden * "}" * writeln } 425 | if$ 426 | } 427 | 428 | FUNCTION { format.articleno } 429 | { 430 | articleno empty.or.unknown not eid empty.or.unknown not and 431 | { "Both articleno and eid are defined for " cite$ * warning$ } 432 | 'skip$ 433 | if$ 434 | articleno empty.or.unknown eid empty.or.unknown and 435 | { "" } 436 | { 437 | numpages empty.or.unknown 438 | { "articleno or eid field, but no numpages field, in " 439 | cite$ * warning$ } 440 | { } 441 | if$ 442 | eid empty.or.unknown 443 | { "Article \bibinfo{articleno}{" articleno * "}" * } 444 | { "Article \bibinfo{articleno}{" eid * "}" * } 445 | if$ 446 | } 447 | if$ 448 | } 449 | 450 | FUNCTION { format.year } 451 | { % push year string or "[n. d.]" onto output stack 452 | %% Because year is a mandatory field, we always force SOMETHING 453 | %% to be output 454 | "\bibinfo{year}{" 455 | year empty.or.unknown 456 | { "[n. d.]" } 457 | { year } 458 | if$ 459 | * "}" * 460 | } 461 | 462 | FUNCTION { format.day.month } 463 | { % push "day month " or "month " or "" onto output stack 464 | day empty.or.unknown 465 | { 466 | month empty.or.unknown 467 | { "" } 468 | { "\bibinfo{date}{" month * "} " *} 469 | if$ 470 | } 471 | { 472 | month empty.or.unknown 473 | { "" } 474 | { "\bibinfo{date}{" day * " " * month * "} " *} 475 | if$ 476 | } 477 | if$ 478 | } 479 | 480 | FUNCTION { format.day.month.year } % UTAH 481 | { % if month is empty, push "" else push "(MON.)" or "(DD MON.)" 482 | % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.) 483 | % acm-*.bst addition: prefix parenthesized date string with 484 | % ", Article nnn " 485 | articleno empty.or.unknown eid empty.or.unknown and 486 | { "" } 487 | { output.state after.block = 488 | {", " format.articleno * } 489 | { format.articleno } 490 | if$ 491 | } 492 | if$ 493 | " (" * format.day.month * format.year * ")" * 494 | } 495 | 496 | FUNCTION { output.day.month.year } % UTAH 497 | { % if month is empty value, do nothing; else output stack top and 498 | % leave with new top string "(MON.)" or "(DD MON.)" 499 | % Needed for frequent periodicals: 2008. ... New York Times C-1, C-2, C-17 (23 Oct.) 500 | format.day.month.year 501 | output.nonnull.remove 502 | } 503 | 504 | FUNCTION { strip.doi } % UTAH 505 | { % Strip any Web address prefix to recover the bare DOI, leaving the 506 | % result on the output stack, as recommended by CrossRef DOI 507 | % documentation. 508 | % For example, reduce "http://doi.acm.org/10.1145/1534530.1534545" to 509 | % "10.1145/1534530.1534545". A suitable URL is later typeset and 510 | % displayed as the LAST item in the reference list entry. Publisher Web 511 | % sites wrap this with a suitable link to a real URL to resolve the DOI, 512 | % and the master https://doi.org/ address is preferred, since publisher- 513 | % specific URLs can disappear in response to economic events. All 514 | % journals are encouraged by the DOI authorities to use that typeset 515 | % format and link procedures for uniformity across all publications that 516 | % include DOIs in reference lists. 517 | % The numeric prefix is guaranteed to start with "10.", so we use 518 | % that as a test. 519 | % 2017-02-04 Added stripping of https:// (Boris) 520 | doi #1 #3 substring$ "10." = 521 | { doi } 522 | { 523 | doi 't := % get modifiable copy of DOI 524 | 525 | % Change https:// to http:// to strip both prefixes (BV) 526 | 527 | t #1 #8 substring$ "https://" = 528 | { "http://" t #9 t text.length$ #8 - substring$ * 't := } 529 | { } 530 | if$ 531 | 532 | t #1 #7 substring$ "http://" = 533 | { 534 | t #8 t text.length$ #7 - substring$ 't := 535 | 536 | "INTERNAL STYLE-FILE ERROR" 's := 537 | 538 | % search for next "/" and assign its suffix to s 539 | 540 | { t text.length$ } 541 | { 542 | t #1 #1 substring$ "/" = 543 | { 544 | % save rest of string as true DOI (should be 10.xxxx/yyyy) 545 | t #2 t text.length$ #1 - substring$ 's := 546 | "" 't := % empty string t terminates the loop 547 | } 548 | { 549 | % discard first character and continue loop: t <= substring(t,2,last) 550 | t #2 t text.length$ #1 - substring$ 't := 551 | } 552 | if$ 553 | } 554 | while$ 555 | 556 | % check for valid DOI (should be 10.xxxx/yyyy) 557 | s #1 #3 substring$ "10." = 558 | { } 559 | { "unrecognized DOI substring " s * " in DOI value [" * doi * "]" * warning$ } 560 | if$ 561 | 562 | s % push the stripped DOI on the output stack 563 | 564 | } 565 | { 566 | "unrecognized DOI value [" doi * "]" * warning$ 567 | doi % push the unrecognized original DOI on the output stack 568 | } 569 | if$ 570 | } 571 | if$ 572 | } 573 | 574 | % 575 | % Change by BV: added standard prefix to URL 576 | % 577 | FUNCTION { output.doi } % UTAH 578 | { % output non-empty DOI as one-line sentence (stack untouched) 579 | doi empty.or.unknown 580 | { } 581 | { 582 | % hacked modification to ensure that underscores are shown right 583 | "\href{https://doi.org/" strip.doi * "}{\detokenize{https://doi.org/" * strip.doi * "}}" * writeln 584 | } 585 | if$ 586 | } 587 | 588 | FUNCTION { output.isbn } % UTAH 589 | { % output non-empty ISBN-10 and/or ISBN-13 as one-line sentences (stack untouched) 590 | show-isbn-10-and-13 591 | { 592 | %% show both 10- and 13-digit ISBNs 593 | isbn empty.or.unknown 594 | { } 595 | { 596 | "\showISBNx{" isbn * "}" * writeln 597 | } 598 | if$ 599 | isbn-13 empty.or.unknown 600 | { } 601 | { 602 | "\showISBNxiii{" isbn-13 * "}" * writeln 603 | } 604 | if$ 605 | } 606 | { 607 | %% show 10-digit ISBNs only if 13-digit ISBNs not available 608 | isbn-13 empty.or.unknown 609 | { 610 | isbn empty.or.unknown 611 | { } 612 | { 613 | "\showISBNx{" isbn * "}" * writeln 614 | } 615 | if$ 616 | } 617 | { 618 | "\showISBNxiii{" isbn-13 * "}" * writeln 619 | } 620 | if$ 621 | } 622 | if$ 623 | } 624 | 625 | FUNCTION { output.issn } % UTAH 626 | { % output non-empty ISSN as one-line sentence (stack untouched) 627 | issn empty.or.unknown 628 | { } 629 | { "\showISSN{" issn * "}" * writeln } 630 | if$ 631 | } 632 | 633 | FUNCTION { output.issue } 634 | { % output non-empty issue number as a one-line sentence (stack untouched) 635 | issue empty.or.unknown 636 | { } 637 | { "Issue " issue * "." * writeln } 638 | if$ 639 | } 640 | 641 | FUNCTION { output.lccn } % UTAH 642 | { % return with stack untouched 643 | lccn empty.or.unknown 644 | { } 645 | { "\showLCCN{" lccn * "}" * writeln } 646 | if$ 647 | } 648 | 649 | FUNCTION { output.note } % UTAH 650 | { % return with stack empty 651 | note empty.or.unknown 652 | { } 653 | { "\shownote{" note add.period$ * "}" * writeln } 654 | if$ 655 | } 656 | 657 | FUNCTION { output.note.check } % UTAH 658 | { % return with stack empty 659 | note empty.or.unknown 660 | { "empty note in " cite$ * warning$ } 661 | { "\shownote{" note add.period$ * "}" * writeln } 662 | if$ 663 | } 664 | 665 | FUNCTION { output.eprint } % 666 | { % return with stack empty 667 | eprint empty.or.unknown 668 | { } 669 | { "\showeprint" 670 | archiveprefix empty.or.unknown 671 | { eprinttype empty.or.unknown 672 | { } 673 | { "[" eprinttype "]" * * * } 674 | if$ 675 | } 676 | { "[" archiveprefix "l" change.case$ "]" * * * } 677 | if$ 678 | "{" * 679 | primaryclass empty.or.unknown 680 | { eprintclass empty.or.unknown 681 | { } 682 | { eprintclass "/" * * } 683 | if$ 684 | } 685 | { primaryclass "/" * * } 686 | if$ 687 | eprint "}" * * 688 | writeln 689 | } 690 | if$ 691 | } 692 | 693 | 694 | % 695 | % Changes by BV 2011/04/15. Do not output 696 | % url if doi is defined 697 | % 698 | FUNCTION { output.url } % UTAH 699 | { % return with stack untouched 700 | % output URL and associated lastaccessed fields 701 | doi empty.or.unknown 702 | { 703 | url empty.or.unknown 704 | { } 705 | { 706 | %% Use \urldef, outside \showURL, so that %nn, #, etc in URLs work 707 | %% correctly. Put the actual URL on its own line to reduce the 708 | %% likelihood of BibTeX's nasty line wrapping after column 79. 709 | %% \url{} can undo this, but if that doesn't work for some reason 710 | %% the .bbl file would have to be repaired manually. 711 | "\urldef\tempurl%" writeln 712 | "\url{" url * "}" * writeln 713 | 714 | "\showURL{%" writeln 715 | lastaccessed empty.or.unknown 716 | { "" } 717 | { "Retrieved " lastaccessed * " from " * } 718 | if$ 719 | "\tempurl}" * writeln 720 | } 721 | if$ 722 | } 723 | { } 724 | if$ 725 | } 726 | 727 | FUNCTION { output.year.check } 728 | { % warn if year empty, output top string and leave " YEAR