From fc90b6eda0f684751440356b873b02787fcbbb62 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Thu, 27 Aug 2026 22:17:50 -0700 Subject: [PATCH 1/8] Reuse recorded integrity in update_versions GitHub only exposes asset digests for recent releases, so every run re-downloaded 1.5 GB of archives to hash releases that were already recorded. Read the integrity values back out of versions.bzl first and fall back to downloading only for assets that have neither. Sort the generated mapping so a new release shows up as an addition rather than reordering the whole file. --- tools/update_versions/update_versions.py | 34 +++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/tools/update_versions/update_versions.py b/tools/update_versions/update_versions.py index 8c78ee4..ae836ed 100644 --- a/tools/update_versions/update_versions.py +++ b/tools/update_versions/update_versions.py @@ -1,6 +1,7 @@ """A script for fetching all available versions of Typst.""" import argparse +import ast import base64 import binascii import hashlib @@ -126,7 +127,28 @@ def compute_integrity_from_url(url: str) -> str | None: return None -def query_releases() -> dict[str, dict[str, dict[str, str]]]: +def recorded_integrity(path: Path) -> dict[str, str]: + """Read integrity values already written to `path`, keyed by download url. + + Releases published before GitHub exposed asset digests would otherwise have + to be downloaded again on every run. + """ + if not path.exists(): + return {} + + match = re.search(r"TYPST_VERSIONS = (\{.*\})", path.read_text(), re.DOTALL) + if not match: + return {} + + return { + url: data["integrity"] + for platforms in ast.literal_eval(match.group(1)).values() + for data in platforms.values() + for url in data["urls"] + } + + +def query_releases(known: dict[str, str]) -> dict[str, dict[str, dict[str, str]]]: """Fetch Typst releases and return version -> platform -> {urls, integrity}.""" page = 1 releases_data: dict[str, dict[str, dict[str, str]]] = {} @@ -164,6 +186,8 @@ def query_releases() -> dict[str, dict[str, dict[str, str]]]: integrity_val = ( _integrity_from_digest(digest) if digest else None ) + if integrity_val is None: + integrity_val = known.get(url_str) if integrity_val is None: logging.info("Computing integrity for %s %s", version, name) integrity_val = compute_integrity_from_url(url_str) @@ -217,10 +241,14 @@ def main() -> None: else: logging.basicConfig(level=logging.INFO) - releases = query_releases() + releases = query_releases(recorded_integrity(args.output)) logging.debug("Writing to %s", args.output) - args.output.write_text(BUILD_TEMPLATE.format(json.dumps(releases, indent=4))) + # Sorted so a new release shows up as an addition rather than reordering + # the whole file. + args.output.write_text( + BUILD_TEMPLATE.format(json.dumps(releases, indent=4, sort_keys=True)) + ) logging.info("Done") From 7e8fa80a3346b6a3f40e54d096aca6e4240828e2 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Thu, 27 Aug 2026 22:17:57 -0700 Subject: [PATCH 2/8] Report only that a checked-in PDF changed write_source_file runs plain diff when its test fails, which dumps xref offsets and compressed font streams into the log; a ten page document produces several hundred lines of noise. Pass --brief so the failure reports the file and the command that regenerates it. --- examples/BUILD.bazel | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 5bd5435..e6a0a90 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -47,6 +47,9 @@ typst( write_source_file( name = "write_example_pdf", + # A PDF is binary, so report only whether it changed rather than dumping + # xref tables and font streams into the test log. + diff_args = ["--brief"], diff_test = True, in_file = ":example", out_file = "generated/source_sync/example.pdf", From ed7b5de6a144af858a4bb92748386b52af62a94b Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Fri, 28 Aug 2026 06:34:05 -0700 Subject: [PATCH 3/8] Ignore host fonts when compiling Typst searches the host font directories, so a document that renders with a system font embeds whichever build of that font the machine happens to have. Two machines with the same Typst version and the same sources then produce different PDFs, which shows up as an unexplained diff test failure against a checked-in copy. Those directories are not declared inputs, so the action was neither reproducible nor correctly invalidated, and a remote cache hit could carry one machine's fonts to another. Pass --ignore-system-fonts so only the fonts embedded in the pinned compiler are available. The checked-in example PDF is regenerated: its monospace text was picking up a host copy of DejaVu Sans Mono. --- README.md | 34 ++++++++++++++++++ examples/generated/source_sync/example.pdf | Bin 27367 -> 27364 bytes .../process_wrapper/process_wrapper.rs | 4 ++- typst/private/tests/fonts/BUILD.bazel | 24 +++++++++++++ typst/private/tests/fonts/embedded_fonts.typ | 1 + typst/private/tests/fonts/host_fonts.typ | 2 ++ typst/private/typst.bzl | 5 ++- 7 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 typst/private/tests/fonts/BUILD.bazel create mode 100644 typst/private/tests/fonts/embedded_fonts.typ create mode 100644 typst/private/tests/fonts/host_fonts.typ diff --git a/README.md b/README.md index 5ef453f..7c14999 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,40 @@ Bazel rules for [Typst](https://typst.app/). +## Reproducibility + +Compilation sees only the declared inputs, so the same sources produce the same +PDF bytes on every machine: + +- `SOURCE_DATE_EPOCH=0` fixes the document's creation timestamp. Override it + through the `env` attribute to opt out. +- Fonts installed on the host are ignored. Only the fonts embedded in the pinned + compiler are available. + +Fonts are the usual source of "works on my machine": a document that renders +with a system font produces a different glyph subset — and therefore different +bytes — wherever that font's build differs. Typst reports an unknown font family +as a warning and silently falls back to a default. + +Hermetic font handling requires Typst 0.12 or newer, when +`--ignore-system-fonts` was added. + +## Checking in generated PDFs + +`write_source_file` runs `diff` when its test fails, which prints thousands of +lines of xref offsets and compressed font streams for a PDF. Pass `--brief` so +the log reports only that the file changed: + +```python +write_source_file( + name = "write_report_pdf", + diff_args = ["--brief"], + diff_test = True, + in_file = ":report", + out_file = "generated/report.pdf", +) +``` + ## Development ### Pre-commit hooks diff --git a/examples/generated/source_sync/example.pdf b/examples/generated/source_sync/example.pdf index 917cb44baafdb59d6c7d38ab2a90e94e26513e36..7d2e502c7929a42384e9a5e3c710cd1bdb308631 100644 GIT binary patch delta 6299 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 delta 6304 zcmZ`+WmJ?6lm-cvlo}e8MnYidbVO+wx^w96j#ofHS{iAPt|5jTKtWQv8x#bFP!I+N zkl1f`f9yH??cQJaJkO1DpL6ez`*R+9Zyvkhrwq14+FJ^mG^jCA+GAOE0L1l-^Z^@N zDsF!|PbP~}#B}u|C1)o-J!ihfAWs1r?*5+2EaUermd;fO5Pek}@siWhS_|gm2w_O= zYOuj#CzuEP_h{(;^6vN^vw>rY^{RpP9lGh9xZo^#Sst4KAA$bXnIYou;Jks2aKoCc ztKBd(x;vtf!*>w-exj=fq-PFsScEY>I>XL3)YH?V^U<6QZy?1sHPD;&$g(B|@H{%P z6YA^vcoNlZ$_ld84o=;15zr=jIp098?kJ-z7W3 zRMtD=I`f#B8*vu-u#dj}`09C%;SGKytNY-@D%Xz`(bGmcG zx5Qh&!^a?Uc4-ZGj98$9KjKOHM>;$v`!d2aR(btUPy9qQ(`b2?XI}nm>EMU5Yn$*W zNe{Ust%o_4k)S56T6}2Z9=34rkdtTf0&bz`!@2-70O!l$QnYIT4YU{p=NWBnh&iF} zdT)oeZ1ZD^|HA^94>|`)=&nMI3|U>PN~@Md{f7FCoNHuHo=iM&CfXK?cgv`5EN%W(c1Q4} zL^Ou_40cPb3uC^hn$$m>wfpXSO=EKMfn!NHlwdthUw9wfNDqBL6KRaqk{&f*`G#WC zvHK5i!5e~2Wh8=wkT|nyJt5SX-C3c=?=k#SCV{}?44RP_mOR1JyZA@Bnv+N@G4rO? zb`3iDrXg{lh@C2f`DCMK>MZTeAMO!(CYk7UZ>(n0cdqEmdee{Hn#>c_jNe&FG_|L& zWw`$wRS*}bD;Ed`7Y_}U5E9ckFk~5M}U+7!U>c6`F zLGNhYIR}5Nkm1ot*wjx-uJXr-(I#j`lC{Ao~bWLjg!1-yVWEHjoTaA{;YU;-|DV2H-w%#hO zRknj=rm=G*Omtdpsq^yaB`r6*S$(9{n)XyXY`@Cg>_i4(&W@&vbHf_0kaG7w-I*Kz zGMW4RO!{^aH4a~wUioCZVPv4?f4XyMZ{7p=16NsLmo|T=Q!uW10g>)w*%IDDOqo4G zK4yUiZTsppkqU4zUS03#*U52&1Pez=sCF&SK-O&-!!yrMXeHrh)=s3vsghcJRU4ac zcJN@5&$|RVx1rh}qV_54yBb^!&S)P$j9($xY0ekfEK+_~YVjt$>2!^K{AtK$pm8iA)<~?>v5NOFI`*F-(bu)Dsp{&g z<~d>a6TdAo8BDuRPu7sfNE+SC{zZ*@mp@@Le+TB~R#olPpgtt4ZH_=N45p~Bzg#j- zA-q=^b9}Xn+14}7t?#ONF_-%!79it7Cn-=0Dte!2n9M=!oF7}uCAh|-9<72?5o8J; z>BMhXO$QMv3Q&J{{|cWGFH{~;<+OKihO1pg^KbxwV9Dp5#+iL-7d`40rDC!4_jk?Y z3u*1)9x=GrVrh(S1FfZ#1)$O5X7f|o3j|MjvKnrJ~L<1?2 z36{)z0EaC5d!pxQk%#1?G)7`c)FXn&3qDIkS+lNrIcv*O9bkE_I;6dqeOsxSBzT*3 zTit(7omX3EC}A>AtVQLb)UdVoPyaH-WE{U}0U*!d+P!wMLq&QlSI_5e+xE8jRHZ;R z)<68oHt}?WnZ4)KmXZN20LE5;+Dnew#3C9$Vft#i4w*%!Jnl36&mEsbOHxpY4K3|c zDomZ;2M)(@M&CjyIvwrHQ+>E-2pGP`oeDlsrlmG4+v`EMR662_d9vHVGy@qz^s z^Mbo2oEM=6tCu5b(5%ctJ&8VjoNG|`V-CAOR+oz>5z5IDQW423jH2`rrh`=)sya|i zRpF>96vII)kZlD7eYau)Gw$=wDv5QUG=+S1o)~lyUCnmw%oK{hu`BsV>&V{Pvr~?Y zFOUjAX&%&=5G+7T6RWm2uCI2|u1~@Azm?l3z8UQUsT=PMO9Nw~L}M5Qrx=3Ss-qGz zzmu$hdHbjcR@1HiQCR^iWSX^EK!*Fv%w<9)s%I?iW*$f@2SSrjRQ87Cv+kQFrs$KI zkez#mw8#?=p5+S<@mgLJ5O}b^Va4#3KzuEp6a?z*v-vfxtb-OzBc#u zm9;M4L%=Uce)L`uGm(mS!~q&n6Lk!K6nKVSt>~P{%e?5qLg9&uMUX}7y1Pt4-uX!~ z4Qb{2X;yrEHa2Jvi~jmsSVLWQab2pzWF^hB-ard%zN@a^MLQ|PNH&j11)@Pk) z(vmIg=@P4J$v8#aoRQyqy@XF^eT^nKKBuhn2F&8^=&~$Imo2TQ-||6O8FoZ9=(dB% z2!8!@afq>bZ`wP_VYvo+$er9>Z^=9AK?fq$ZVjm;-uDqc`OeBYt?7J;!$g@K26xYS zY;?@24rQmZFcW2avW{tjPiB3x0C>(WBLzL3ScsZHM-FRAgvnNkabML=XHxr#wRLh5 zKu~Xq-y-jt`J8QpRea*DL%{ch0XE=DH6$L=iK}Z zFH#@PY+$gnhw$3pZN=Q=;iG>9&3?!Oem{~qu*@NzwKcEFoA_|f=6WgtXn?`fh=gC0 z&q6PY=lwTUkIvKsI`5E^!|4ko-%5MB)GhANr$Qg+=p_3?LhCn5+jI9Br-#-__L%$< zl9GhYp6O6URw!NAakUI~c!#3Z4`%J>8>evut?5Y^Q_-QvP`R45ud-{c=RJ&o)bG_! z*S(#>6^1%?!v5s`zgsW1DhQVb#Gr-ylIItWgptn$Ej}AqkWjC5MOjTx2qX$Cz6UYT zsh577=5J3xdElIm3ist%{g~FUH!L6{!?*W{zs=s4rn92^VMQW!RR7cUbJOvL^(bLh3u1HAUC^QfAdhro>^A2d+ zH9Pxp(oZ(o{IN_eLWui18NE74Vo#o1>#?cM_DvYK(MfKs9yA!(^p1drlsvR5n$c*;D$$wi5$1wjbV zbSt#Y2$8^wD5|n*nJ{NncyLW$=<<1Mmr-Tr3-#>gORClqLiMExmB2Qu8c!ni0PG!y zK0%)%l^~vDkEJ2g+SHcDtYvmSJrj7h+CS>Nm_0_*ght(g#CY>P9E)j^MH(QH;WCdN zTt2XikT(#UVtgtfL!$}!3)YN(hs1oYd-mw_d7I=U=Zgf|*aX;w4@BC2RXsbc?Z>65i0($2_D}Qj`?>(M#a+?qQ%| z6#m>N>_g3P?YXD4Oq5o9-#!qKdTAv(1qf6?^}B2VDh*Xn|0xb#kC45M03ibxU-!<}kh(MoeE@;PZ%4@Q6E*3vG0x2hT6Qu&6- zNh@9?8;)MI&N#>_C}W{W!>=Q)C8=fPMQWcLGl^VwXEBKukw_@X(|x-=Tl_>;RjJ5F z*GOVpsp-7PeXQLGq5>Sgq+`!K*udBPOlK>>L6+XEU-V$Uasb~HE^xmI(H`vgR38U< zm7NeZT{$g?e>jD9m0bXM6f%X|XV2y0gm#-02MuAZB+lO~IC;!@VMQ zq)MXR<*jiQLMgp0R9mBrt`0S8_ht!}#^C<4uF0d$*kW(511Kv7@l1VBZn!bo$CQmF z`@FP^Y=Q|4scMz)&KFI*ka-H3Xmx4J)-7%tgn9H~WwKQckF@L@m|UC33)Q}=+LVir zv~_r$n9AbniuzhXUZeSI@6VDf{a=yckgN+a%gDk#ZEHD>rV5fn&3G^2=Td*`xDA+w z-`DjK2tNZfdl0WE zd6tf1FOhBOk4@+e*c4wD-_^ z{MFa$pJjz)Q10bwYM~2}1LWthkQ75<%TG;h+IraBQoc{L3tRMIO^uUbRc0`LZwbxm z(qE|+hu1(5uPS>v_6u9-hfVwqfHEJ*Jh4(AddoD@LcW|41~R^@f8BCg{%y0(?Im%> zhEe7mW}hYwdb@Wm+%T9y3d=^LS3n`H?2+fh13Si|#$5G!Ii;M1=JR!2BTz?+@uwZ( z1=q56_@{O#e(fJ{|Cy~Yb^3IJ9jDMfk&A(MvcTt<`VVI~NVh($R-+EE_pmIhXX8cr z+qzWZc^sBTrWQkA;{N9zS$)eeckTntz0Coei_vwC2AJgyU#^^#wGG2g_DwxzmFqkN zWWjq}ulIGw;Zu$X&5w7J(r`ASxF7ez_O^+2zgL_8HuHbbI>oixDOk&@y|t};-BC{D ztO-=_Dvd1ka2ffYUv1x)z(P9>7L-R{Y5k7R2vt&-FP;Gt4rJG$$NDJ81|Ix`CDHM` zdMurtD3Kj?#q|oCK&xmgwMOA*K*YB}JT7f=d#i#}+mY-@Q}$poX_Z##Do{-YE!QhS zg1MDfytMaKr!D7o_&Xqy3=tL)f7F3n$62f|MKJcGRFe0!VaE{(kT z@kTfZl2#QJ{{7}7QA!xeso=O=PP{ZFci>D|6%gk{jail$aCfZlQ&PzkIuj%X&!-*b z$4F!+8gXd_sEpu+Imc&^>Ie)Ss}?tXiF;?OC2MCT3aX;j5hV7`pwgZ-y;r-EHUO?z zS-o>-B<0VIGsjOAjavVf4F|uSb6kG*r*N~PRJW|O?E_(?~59n|fuluib& zV_Vdq^iClHt`x{+J1iJm((i4zIVOQq!eX6Mv&F%eby&tpo|5VuME*fkTyhbn_%bq` zeVZdCr^+tNQj{PC&SoS7VvbLTUjbn*d>=u_d>V${e7QCuae6lHL(=y|svDXwYKc-V zFu_)Do-W>hl*4MiL#f8j?7o#r9Z$72_{4GsHD<9_1`StW5u{oRsbucx_ZUh(@XXuW zvwwOP7xSHd_|uoJ7ur(1M%e3-tXzN6#f?D58KswmBP~t_&wgwB!Y4k%=PiI1Z&GQQ zi$ax$1#)Q*=T^cwv1qFk7)UQBmT+2ZNgjBg9?VF>r0(aHfl zeAoV$ro8+68BlCWdKaW+#~n~!h%MF~Pw}?BUzc|q$RxFp#>cjhB?XpE;C@8AKN(-Pl9X?2XnBEW`wlChVik+7eo(dbqV9~(w?FpEe1{$sUk<)p_Eo?wMjO!vuN zm9$uFloiGMD3-_luRdVINZ4N(juS*s^dD8b>Ug(19ab0WCYJ|g`=>m8hC1aqphCwM zC4*7Szt9+U^mG~M4oE3VPC{kz^KWGtqh{=GVUrGFo@8d|1DQ|z?tuC>@HhJ|N8z3w zB@Y2ciU{4VEvbF)1D_v*=6)ehqcL%JdsY8DJ6?Bp{E`+L06BVtIpz$5d+RBF3z_N= zLDv^;w#_bY4xBbK&mP0}^UcsEkk4f3i;qfotwrDzpCEwx_PS2#&KctVi|B{@n;E$1 zbgsl)3;3P?&J;I<6WIUGiFZ2#aes6jRYW1B76!w;wWsXnN9`d|0p8?t{3!c~u+G>p z7SvEg7#pgk+p0@vN)V!mcdI#-lK<@HeXcoiS(3p@U`&w#$%`F0VwNZO{Od2}n-gux zqxsb|6krR9@k@b=WPN5sSvvE}T?*a~Z3x_z6fvjI67HanH6*{691{ka2fUcY;L32K zko-aVQ(&mn6_^%{Nb70d{JBZ1`d9t>LWlciH5XMyd7W9ri5IG)xk}O4RhL(A8Qoj> zzRaBl?fdW-1^V)z((OgvRtS6l=bNk!{?BEAg`835)i+2c*F7Yz%=NJLor9E2rxEb8 zm+fv?JE*@#ju+(|!4xDAD>tV>%Aw`#P3}Hk_Ruf-%;Oj7K@Fs0(#rlPO*?D#FghvXfQZahD2OYsVlh zqC(l&xKpz(uIO^A!4t=b@?GTRoL7!E&DRQqjujErPh>zZ+qX$@U{CyMXwD*i?cPrG znRMD|2whiiQ2pYF_gC)4p`?IF-{ZRCwL>;|vg-x@VOuo*nThehcKt^WP%&spzl|#CUJbSf5 zOv%mQJ12*DiB!T0Qz#D=Anx0?a+HsmI6HyLBhtOc5nD3c(qR;V+75F>ap1FnyrPr{ z1)}5~R$Stk-k6~o0Z3y64EK%V&L0#vCDq5iPp4cnt|!BkUi6gMk&5jjw!5BLPt(dg zz{v?G9&Xt-hD%XW@__;3Q6@_gUm4bDRWt~Z4O5m(yF~)bXFZiMukm#%e=e}ey#Bx{ z9w&v1r>OM-;s+7U>~oE1&s7@zffjV+jdGUgxAe$-CGh^r@MtPS`feWoCJml) z>3&`fFg8Q<+DWLyh1K;uHN`{}487ePgkO2<2MIxh(nxH${%@vP)kYH!5PK@{pZ3&^ znBc!0Awh9*@V_t#L5cs32?>e)D_2NV;@@#%B7*-r7c3wq^xv51|1=gB75!IZVKK3P z6%-K{6;9K1QqcH6=hc#t;eN{X|59cIva$r;K2}~n0baIt1VW+$5)uUL>~Ek7{{dZs BA@%?O diff --git a/typst/private/process_wrapper/process_wrapper.rs b/typst/private/process_wrapper/process_wrapper.rs index 4314647..580df0a 100644 --- a/typst/private/process_wrapper/process_wrapper.rs +++ b/typst/private/process_wrapper/process_wrapper.rs @@ -98,11 +98,13 @@ fn main() { .expect("src rlocationpath must have a workspace name component"), ); - // Run the typst compiler + // Run the typst compiler. Host fonts are excluded so output does not + // depend on which font packages the machine has installed. let result = Command::new(&args.compiler) .arg("compile") .arg("--root") .arg(&workspace_root) + .arg("--ignore-system-fonts") .arg(&abs_src) .arg(&args.out) .output(); diff --git a/typst/private/tests/fonts/BUILD.bazel b/typst/private/tests/fonts/BUILD.bazel new file mode 100644 index 0000000..71b4e6a --- /dev/null +++ b/typst/private/tests/fonts/BUILD.bazel @@ -0,0 +1,24 @@ +load("@bazel_skylib//rules:diff_test.bzl", "diff_test") +load("//typst:typst.bzl", "typst") + +# A document asking for font families that Typst does not embed. The families +# are common on developer and CI machines, so if host fonts were searched this +# would render with one of them instead of falling back. +typst( + name = "host_fonts", + src = "host_fonts.typ", +) + +typst( + name = "embedded_fonts", + src = "embedded_fonts.typ", +) + +# Both documents must fall back to the same embedded font. A failure here means +# a host font leaked into the output, which makes the PDF differ between +# machines depending on which font packages are installed. +diff_test( + name = "host_fonts_ignored_test", + file1 = ":host_fonts", + file2 = ":embedded_fonts", +) diff --git a/typst/private/tests/fonts/embedded_fonts.typ b/typst/private/tests/fonts/embedded_fonts.typ new file mode 100644 index 0000000..4fe2209 --- /dev/null +++ b/typst/private/tests/fonts/embedded_fonts.typ @@ -0,0 +1 @@ +hermetic diff --git a/typst/private/tests/fonts/host_fonts.typ b/typst/private/tests/fonts/host_fonts.typ new file mode 100644 index 0000000..6544cec --- /dev/null +++ b/typst/private/tests/fonts/host_fonts.typ @@ -0,0 +1,2 @@ +#set text(font: ("Arial", "Helvetica", "DejaVu Sans", "Liberation Sans", "Noto Sans")) +hermetic diff --git a/typst/private/typst.bzl b/typst/private/typst.bzl index 7894ea9..3ac724e 100644 --- a/typst/private/typst.bzl +++ b/typst/private/typst.bzl @@ -52,7 +52,10 @@ def _typst_impl(ctx): ] typst = rule( - doc = "Compile a Typst document to PDF.", + doc = "Compile a Typst document to PDF.\n\n" + + "Compilation sees only the declared sources and the fonts embedded in " + + "the pinned compiler. Fonts installed on the host are ignored so the " + + "same inputs produce the same bytes on every machine.", implementation = _typst_impl, attrs = { "data": attr.label_list( From 222f75c231311e48f7307902e4896fd150e094a8 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Fri, 28 Aug 2026 06:35:42 -0700 Subject: [PATCH 4/8] Resolve Typst packages inside the action A `@preview` import resolves against a system-dependent package directory and download cache, so a document could compile against whatever a developer happened to have in ~/.cache/typst and fail elsewhere. Same failure mode as host fonts. Point --package-path and --package-cache-path at a directory created for the action, alongside the runfiles tree and outside the document root. --- README.md | 2 + .../process_wrapper/process_wrapper.rs | 37 +++++++++++++------ typst/private/typst.bzl | 4 +- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7c14999..098a411 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ PDF bytes on every machine: through the `env` attribute to opt out. - Fonts installed on the host are ignored. Only the fonts embedded in the pinned compiler are available. +- The package path and package cache point inside the action, so a `@preview` + import cannot resolve against a developer's `~/.cache/typst`. Fonts are the usual source of "works on my machine": a document that renders with a system font produces a different glyph subset — and therefore different diff --git a/typst/private/process_wrapper/process_wrapper.rs b/typst/private/process_wrapper/process_wrapper.rs index 580df0a..4d4e942 100644 --- a/typst/private/process_wrapper/process_wrapper.rs +++ b/typst/private/process_wrapper/process_wrapper.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; /// Command line args for the process wrapper. @@ -57,10 +57,12 @@ impl Args { } } -fn cleanup(temp_runfiles_dir: &PathBuf) { - if temp_runfiles_dir.exists() { - fs::remove_dir_all(temp_runfiles_dir) - .unwrap_or_else(|e| eprintln!("Warning: failed to clean up temp dir: {}", e)); +fn cleanup(temp_dirs: &[&Path]) { + for dir in temp_dirs { + if dir.exists() { + fs::remove_dir_all(dir) + .unwrap_or_else(|e| eprintln!("Warning: failed to clean up temp dir: {}", e)); + } } } @@ -69,8 +71,14 @@ fn main() { let temp_runfiles_dir = PathBuf::from(format!("{}.runfiles", args.out.display())); - // Create the temp runfiles directory - fs::create_dir_all(&temp_runfiles_dir).expect("Failed to create temp runfiles directory"); + // Packages resolve inside the action, and outside the document root so + // they cannot be referenced as document sources. + let package_dir = PathBuf::from(format!("{}.packages", args.out.display())); + let temp_dirs = [temp_runfiles_dir.as_path(), package_dir.as_path()]; + + for dir in temp_dirs { + fs::create_dir_all(dir).expect("Failed to create temp directory"); + } // Copy the source file into the build directory at its rlocation path let abs_src = temp_runfiles_dir.join(&args.src.1); @@ -98,13 +106,18 @@ fn main() { .expect("src rlocationpath must have a workspace name component"), ); - // Run the typst compiler. Host fonts are excluded so output does not - // depend on which font packages the machine has installed. + // Run the typst compiler. Host fonts and the user's package directories + // are excluded so output does not depend on what the machine has + // installed or previously downloaded. let result = Command::new(&args.compiler) .arg("compile") .arg("--root") .arg(&workspace_root) .arg("--ignore-system-fonts") + .arg("--package-path") + .arg(&package_dir) + .arg("--package-cache-path") + .arg(&package_dir) .arg(&abs_src) .arg(&args.out) .output(); @@ -118,7 +131,7 @@ fn main() { String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr), ); - cleanup(&temp_runfiles_dir); + cleanup(&temp_dirs); std::process::exit(1); } @@ -126,11 +139,11 @@ fn main() { print!("{}", String::from_utf8_lossy(&output.stdout)); } - cleanup(&temp_runfiles_dir); + cleanup(&temp_dirs); } Err(e) => { eprintln!("Failed to run typst compiler: {}", e); - cleanup(&temp_runfiles_dir); + cleanup(&temp_dirs); std::process::exit(1); } } diff --git a/typst/private/typst.bzl b/typst/private/typst.bzl index 3ac724e..abcf7f4 100644 --- a/typst/private/typst.bzl +++ b/typst/private/typst.bzl @@ -54,8 +54,8 @@ def _typst_impl(ctx): typst = rule( doc = "Compile a Typst document to PDF.\n\n" + "Compilation sees only the declared sources and the fonts embedded in " + - "the pinned compiler. Fonts installed on the host are ignored so the " + - "same inputs produce the same bytes on every machine.", + "the pinned compiler. Fonts and packages installed on the host are " + + "ignored so the same inputs produce the same bytes on every machine.", implementation = _typst_impl, attrs = { "data": attr.label_list( From cc0ad14dd0089ffb2f564dce804fc01c965993e2 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Fri, 28 Aug 2026 06:37:14 -0700 Subject: [PATCH 5/8] Forward Typst diagnostics on a successful compile The wrapper printed the compiler's stdout and discarded its stderr unless the compile failed. Typst reports an unknown font family as a warning and falls back to a default, so a document could render with the wrong font and leave a clean build log. --- README.md | 3 ++- typst/private/process_wrapper/process_wrapper.rs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 098a411..eacfbeb 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ PDF bytes on every machine: Fonts are the usual source of "works on my machine": a document that renders with a system font produces a different glyph subset — and therefore different bytes — wherever that font's build differs. Typst reports an unknown font family -as a warning and silently falls back to a default. +as a warning and silently falls back to a default, so check the build log if the +output is not what you expect. Hermetic font handling requires Typst 0.12 or newer, when `--ignore-system-fonts` was added. diff --git a/typst/private/process_wrapper/process_wrapper.rs b/typst/private/process_wrapper/process_wrapper.rs index 4d4e942..3796512 100644 --- a/typst/private/process_wrapper/process_wrapper.rs +++ b/typst/private/process_wrapper/process_wrapper.rs @@ -139,6 +139,12 @@ fn main() { print!("{}", String::from_utf8_lossy(&output.stdout)); } + // Diagnostics such as `unknown font family` are reported on a + // successful compile and would otherwise be lost. + if !output.stderr.is_empty() { + eprint!("{}", String::from_utf8_lossy(&output.stderr)); + } + cleanup(&temp_dirs); } Err(e) => { From 1b41ea212ede08874a0831a70b1986c12b5f7529 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Fri, 28 Aug 2026 06:37:38 -0700 Subject: [PATCH 6/8] Run the Typst compiler single threaded Typst defaults to a thread per CPU, which oversubscribes the machine when Bazel schedules several document actions at once. Bazel budgets one CPU per action, so let it own the parallelism. Output is unaffected. --- typst/private/process_wrapper/process_wrapper.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/typst/private/process_wrapper/process_wrapper.rs b/typst/private/process_wrapper/process_wrapper.rs index 3796512..d941af8 100644 --- a/typst/private/process_wrapper/process_wrapper.rs +++ b/typst/private/process_wrapper/process_wrapper.rs @@ -108,9 +108,13 @@ fn main() { // Run the typst compiler. Host fonts and the user's package directories // are excluded so output does not depend on what the machine has - // installed or previously downloaded. + // installed or previously downloaded. Typst otherwise spawns a thread per + // CPU, which oversubscribes the machine when Bazel runs several actions at + // once. let result = Command::new(&args.compiler) .arg("compile") + .arg("--jobs") + .arg("1") .arg("--root") .arg(&workspace_root) .arg("--ignore-system-fonts") From 4c72fd27cf25ab79a55492ae89a01c1215ee5877 Mon Sep 17 00:00:00 2001 From: Matt Epperson Date: Fri, 28 Aug 2026 06:38:02 -0700 Subject: [PATCH 7/8] Update to Typst 0.15.1 Adds the 0.15.0 and 0.15.1 releases to the version matrix and moves the default to 0.15.1. Existing entries are unchanged. The checked-in example PDF is regenerated: a compiler change moves the output bytes. --- MODULE.bazel.lock | 145 +++++++++++++++++++-- examples/MODULE.bazel.lock | 145 +++++++++++++++++++-- examples/generated/source_sync/example.pdf | Bin 27364 -> 24603 bytes typst/private/versions.bzl | 100 ++++++++++++++ typst/settings/BUILD.bazel | 2 +- 5 files changed, 369 insertions(+), 23 deletions(-) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 22e3e6e..db77bf2 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1,5 +1,5 @@ { - "lockFileVersion": 26, + "lockFileVersion": 28, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", @@ -36,8 +36,9 @@ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", "https://bcr.bazel.build/modules/bazel_features/1.32.0/MODULE.bazel": "095d67022a58cb20f7e20e1aefecfa65257a222c18a938e2914fd257b5f1ccdc", "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", - "https://bcr.bazel.build/modules/bazel_features/1.33.0/source.json": "13617db3930328c2cd2807a0f13d52ca870ac05f96db9668655113265147b2a6", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", @@ -53,8 +54,8 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", - "https://bcr.bazel.build/modules/buildozer/8.2.1/MODULE.bazel": "61e9433c574c2bd9519cad7fa66b9c1d2b8e8d5f3ae5d6528a2c2d26e68d874d", - "https://bcr.bazel.build/modules/buildozer/8.2.1/source.json": "7c33f6a26ee0216f85544b4bca5e9044579e0219b6898dd653f5fb449cf2e484", + "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", + "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", @@ -114,8 +115,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", @@ -130,8 +131,8 @@ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/9.0.3/MODULE.bazel": "1f98ed015f7e744a745e0df6e898a7c5e83562d6b759dfd475c76456dda5ccea", - "https://bcr.bazel.build/modules/rules_java/9.0.3/source.json": "b038c0c07e12e658135bbc32cc1a2ded6e33785105c9d41958014c592de4593e", + "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", + "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", @@ -194,9 +195,31 @@ }, "selectedYankedVersions": {}, "moduleExtensions": { + "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": { + "general": { + "bzlTransitiveDigest": "NRXra7941UfmNUyIxnLt82V5hULluVGL2nBsijTl4j4=", + "usagesDigest": "D1r3lfzMuUBFxgG8V6o0bQTLMk3GkaGOaPzw53wrwyw=", + "recordedInputs": [ + "REPO_MAPPING:pybind11_bazel+,bazel_tools bazel_tools", + "FILE:@@pybind11_bazel+//MODULE.bazel e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34" + ], + "generatedRepoSpecs": { + "pybind11": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel", + "strip_prefix": "pybind11-2.12.0", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.12.0.zip" + ] + } + } + } + } + }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=", + "bzlTransitiveDigest": "+Kp6j204mBZ3mxlIDDR0gBoP45BZ4jYRhRAcB8sU0qc=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedInputs": [ "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" @@ -253,7 +276,7 @@ }, "@@rules_python+//python/extensions:config.bzl%config": { "general": { - "bzlTransitiveDigest": "2hLgIvNVTLgxus0ZuXtleBe70intCfo0cHs8qvt6cdM=", + "bzlTransitiveDigest": "dzD8Q2YmrP3fz8saWLHPmlwPLO91ImtTmP/c9JKTStM=", "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", "recordedInputs": [ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", @@ -448,7 +471,107 @@ } } } + }, + "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { + "general": { + "bzlTransitiveDigest": "0sciz0kymc5dgL4oGclX27op/23ntMrEVqLrpW83bvo=", + "usagesDigest": "v4We18mWSPeKV4GPp9Gne78W+jZOgP2pC1i4UN9br1g=", + "recordedInputs": [ + "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", + "REPO_MAPPING:bazel_features+,bazel_features_version bazel_features++version_extension+bazel_features_version", + "REPO_MAPPING:rules_cc+,bazel_skylib bazel_skylib+", + "REPO_MAPPING:rules_cc+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_cc+,cc_compatibility_proxy rules_cc++compatibility_proxy+cc_compatibility_proxy", + "REPO_MAPPING:rules_cc+,platforms platforms", + "REPO_MAPPING:rules_cc+,rules_cc rules_cc+", + "REPO_MAPPING:rules_cc++compatibility_proxy+cc_compatibility_proxy,rules_cc rules_cc+", + "REPO_MAPPING:rules_rust+,bazel_features bazel_features+", + "REPO_MAPPING:rules_rust+,bazel_skylib bazel_skylib+", + "REPO_MAPPING:rules_rust+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_rust+,cui rules_rust++cu+cui", + "REPO_MAPPING:rules_rust+,rrc rules_rust++i2+rrc", + "REPO_MAPPING:rules_rust+,rules_cc rules_cc+", + "REPO_MAPPING:rules_rust+,rules_rust rules_rust+" + ], + "generatedRepoSpecs": { + "cargo_bazel_bootstrap": { + "repoRuleId": "@@rules_rust+//cargo/private:cargo_bootstrap.bzl%cargo_bootstrap_repository", + "attributes": { + "srcs": [ + "@@rules_rust+//crate_universe:src/api.rs", + "@@rules_rust+//crate_universe:src/api/lockfile.rs", + "@@rules_rust+//crate_universe:src/cli.rs", + "@@rules_rust+//crate_universe:src/cli/generate.rs", + "@@rules_rust+//crate_universe:src/cli/query.rs", + "@@rules_rust+//crate_universe:src/cli/render.rs", + "@@rules_rust+//crate_universe:src/cli/splice.rs", + "@@rules_rust+//crate_universe:src/cli/vendor.rs", + "@@rules_rust+//crate_universe:src/config.rs", + "@@rules_rust+//crate_universe:src/context.rs", + "@@rules_rust+//crate_universe:src/context/crate_context.rs", + "@@rules_rust+//crate_universe:src/context/platforms.rs", + "@@rules_rust+//crate_universe:src/lib.rs", + "@@rules_rust+//crate_universe:src/lockfile.rs", + "@@rules_rust+//crate_universe:src/main.rs", + "@@rules_rust+//crate_universe:src/metadata.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_bin.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_resolver.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.bat", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.sh", + "@@rules_rust+//crate_universe:src/metadata/dependency.rs", + "@@rules_rust+//crate_universe:src/metadata/metadata_annotation.rs", + "@@rules_rust+//crate_universe:src/rendering.rs", + "@@rules_rust+//crate_universe:src/rendering/template_engine.rs", + "@@rules_rust+//crate_universe:src/rendering/templates/module_bzl.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/header.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/aliases_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/deps_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_git.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_http.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/vendor_module.j2", + "@@rules_rust+//crate_universe:src/rendering/verbatim/alias_rules.bzl", + "@@rules_rust+//crate_universe:src/select.rs", + "@@rules_rust+//crate_universe:src/splicing.rs", + "@@rules_rust+//crate_universe:src/splicing/cargo_config.rs", + "@@rules_rust+//crate_universe:src/splicing/crate_index_lookup.rs", + "@@rules_rust+//crate_universe:src/splicing/splicer.rs", + "@@rules_rust+//crate_universe:src/test.rs", + "@@rules_rust+//crate_universe:src/utils.rs", + "@@rules_rust+//crate_universe:src/utils/starlark.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/glob.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/label.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_dict.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_list.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_scalar.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_set.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/serialize.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/target_compatible_with.rs", + "@@rules_rust+//crate_universe:src/utils/symlink.rs", + "@@rules_rust+//crate_universe:src/utils/target_triple.rs" + ], + "binary": "cargo-bazel", + "cargo_lockfile": "@@rules_rust+//crate_universe:Cargo.lock", + "cargo_toml": "@@rules_rust+//crate_universe:Cargo.toml", + "version": "1.86.0", + "timeout": 900, + "rust_toolchain_cargo_template": "@rust_host_tools//:bin/{tool}", + "rust_toolchain_rustc_template": "@rust_host_tools//:bin/{tool}", + "compressed_windows_toolchain_names": false + } + } + }, + "moduleExtensionMetadata": { + "explicitRootModuleDirectDeps": [ + "cargo_bazel_bootstrap" + ], + "explicitRootModuleDirectDevDeps": [], + "useAllRepos": "NO", + "reproducible": false + } + } } }, - "facts": {} + "facts": {}, + "factsVersions": {} } diff --git a/examples/MODULE.bazel.lock b/examples/MODULE.bazel.lock index 86f6c2d..7771297 100644 --- a/examples/MODULE.bazel.lock +++ b/examples/MODULE.bazel.lock @@ -1,5 +1,5 @@ { - "lockFileVersion": 26, + "lockFileVersion": 28, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", @@ -36,8 +36,9 @@ "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", "https://bcr.bazel.build/modules/bazel_features/1.32.0/MODULE.bazel": "095d67022a58cb20f7e20e1aefecfa65257a222c18a938e2914fd257b5f1ccdc", "https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6", - "https://bcr.bazel.build/modules/bazel_features/1.33.0/source.json": "13617db3930328c2cd2807a0f13d52ca870ac05f96db9668655113265147b2a6", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080", + "https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309", "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_lib/3.2.1/MODULE.bazel": "5d1dc35da5c2f09910ffa22b07c3fbbb3468702e396d1d8a83c5f21132f77a4f", @@ -56,8 +57,8 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", - "https://bcr.bazel.build/modules/buildozer/8.2.1/MODULE.bazel": "61e9433c574c2bd9519cad7fa66b9c1d2b8e8d5f3ae5d6528a2c2d26e68d874d", - "https://bcr.bazel.build/modules/buildozer/8.2.1/source.json": "7c33f6a26ee0216f85544b4bca5e9044579e0219b6898dd653f5fb449cf2e484", + "https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f", + "https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd", "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", @@ -117,8 +118,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8", - "https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84", + "https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07", "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", @@ -133,8 +134,8 @@ "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/9.0.3/MODULE.bazel": "1f98ed015f7e744a745e0df6e898a7c5e83562d6b759dfd475c76456dda5ccea", - "https://bcr.bazel.build/modules/rules_java/9.0.3/source.json": "b038c0c07e12e658135bbc32cc1a2ded6e33785105c9d41958014c592de4593e", + "https://bcr.bazel.build/modules/rules_java/9.1.0/MODULE.bazel": "ee63f27e36a3fada80342869361182f120a9819c74320e8e65b1e04ba0cd7a9d", + "https://bcr.bazel.build/modules/rules_java/9.1.0/source.json": "da589573c1dee2c9ac4a568b301269a2e8191110ff0345c1a959fa7ea6c4dfd6", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", @@ -196,9 +197,31 @@ }, "selectedYankedVersions": {}, "moduleExtensions": { + "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": { + "general": { + "bzlTransitiveDigest": "NRXra7941UfmNUyIxnLt82V5hULluVGL2nBsijTl4j4=", + "usagesDigest": "D1r3lfzMuUBFxgG8V6o0bQTLMk3GkaGOaPzw53wrwyw=", + "recordedInputs": [ + "REPO_MAPPING:pybind11_bazel+,bazel_tools bazel_tools", + "FILE:@@pybind11_bazel+//MODULE.bazel e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34" + ], + "generatedRepoSpecs": { + "pybind11": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel", + "strip_prefix": "pybind11-2.12.0", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.12.0.zip" + ] + } + } + } + } + }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=", + "bzlTransitiveDigest": "+Kp6j204mBZ3mxlIDDR0gBoP45BZ4jYRhRAcB8sU0qc=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedInputs": [ "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" @@ -255,7 +278,7 @@ }, "@@rules_python+//python/extensions:config.bzl%config": { "general": { - "bzlTransitiveDigest": "2hLgIvNVTLgxus0ZuXtleBe70intCfo0cHs8qvt6cdM=", + "bzlTransitiveDigest": "dzD8Q2YmrP3fz8saWLHPmlwPLO91ImtTmP/c9JKTStM=", "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", "recordedInputs": [ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", @@ -450,7 +473,107 @@ } } } + }, + "@@rules_rust+//crate_universe/private:internal_extensions.bzl%cu_nr": { + "general": { + "bzlTransitiveDigest": "0sciz0kymc5dgL4oGclX27op/23ntMrEVqLrpW83bvo=", + "usagesDigest": "v4We18mWSPeKV4GPp9Gne78W+jZOgP2pC1i4UN9br1g=", + "recordedInputs": [ + "REPO_MAPPING:bazel_features+,bazel_features_globals bazel_features++version_extension+bazel_features_globals", + "REPO_MAPPING:bazel_features+,bazel_features_version bazel_features++version_extension+bazel_features_version", + "REPO_MAPPING:rules_cc+,bazel_skylib bazel_skylib+", + "REPO_MAPPING:rules_cc+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_cc+,cc_compatibility_proxy rules_cc++compatibility_proxy+cc_compatibility_proxy", + "REPO_MAPPING:rules_cc+,platforms platforms", + "REPO_MAPPING:rules_cc+,rules_cc rules_cc+", + "REPO_MAPPING:rules_cc++compatibility_proxy+cc_compatibility_proxy,rules_cc rules_cc+", + "REPO_MAPPING:rules_rust+,bazel_features bazel_features+", + "REPO_MAPPING:rules_rust+,bazel_skylib bazel_skylib+", + "REPO_MAPPING:rules_rust+,bazel_tools bazel_tools", + "REPO_MAPPING:rules_rust+,cui rules_rust++cu+cui", + "REPO_MAPPING:rules_rust+,rrc rules_rust++i2+rrc", + "REPO_MAPPING:rules_rust+,rules_cc rules_cc+", + "REPO_MAPPING:rules_rust+,rules_rust rules_rust+" + ], + "generatedRepoSpecs": { + "cargo_bazel_bootstrap": { + "repoRuleId": "@@rules_rust+//cargo/private:cargo_bootstrap.bzl%cargo_bootstrap_repository", + "attributes": { + "srcs": [ + "@@rules_rust+//crate_universe:src/api.rs", + "@@rules_rust+//crate_universe:src/api/lockfile.rs", + "@@rules_rust+//crate_universe:src/cli.rs", + "@@rules_rust+//crate_universe:src/cli/generate.rs", + "@@rules_rust+//crate_universe:src/cli/query.rs", + "@@rules_rust+//crate_universe:src/cli/render.rs", + "@@rules_rust+//crate_universe:src/cli/splice.rs", + "@@rules_rust+//crate_universe:src/cli/vendor.rs", + "@@rules_rust+//crate_universe:src/config.rs", + "@@rules_rust+//crate_universe:src/context.rs", + "@@rules_rust+//crate_universe:src/context/crate_context.rs", + "@@rules_rust+//crate_universe:src/context/platforms.rs", + "@@rules_rust+//crate_universe:src/lib.rs", + "@@rules_rust+//crate_universe:src/lockfile.rs", + "@@rules_rust+//crate_universe:src/main.rs", + "@@rules_rust+//crate_universe:src/metadata.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_bin.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_resolver.rs", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.bat", + "@@rules_rust+//crate_universe:src/metadata/cargo_tree_rustc_wrapper.sh", + "@@rules_rust+//crate_universe:src/metadata/dependency.rs", + "@@rules_rust+//crate_universe:src/metadata/metadata_annotation.rs", + "@@rules_rust+//crate_universe:src/rendering.rs", + "@@rules_rust+//crate_universe:src/rendering/template_engine.rs", + "@@rules_rust+//crate_universe:src/rendering/templates/module_bzl.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/header.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/aliases_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/deps_map.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_git.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/partials/module/repo_http.j2", + "@@rules_rust+//crate_universe:src/rendering/templates/vendor_module.j2", + "@@rules_rust+//crate_universe:src/rendering/verbatim/alias_rules.bzl", + "@@rules_rust+//crate_universe:src/select.rs", + "@@rules_rust+//crate_universe:src/splicing.rs", + "@@rules_rust+//crate_universe:src/splicing/cargo_config.rs", + "@@rules_rust+//crate_universe:src/splicing/crate_index_lookup.rs", + "@@rules_rust+//crate_universe:src/splicing/splicer.rs", + "@@rules_rust+//crate_universe:src/test.rs", + "@@rules_rust+//crate_universe:src/utils.rs", + "@@rules_rust+//crate_universe:src/utils/starlark.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/glob.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/label.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_dict.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_list.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_scalar.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/select_set.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/serialize.rs", + "@@rules_rust+//crate_universe:src/utils/starlark/target_compatible_with.rs", + "@@rules_rust+//crate_universe:src/utils/symlink.rs", + "@@rules_rust+//crate_universe:src/utils/target_triple.rs" + ], + "binary": "cargo-bazel", + "cargo_lockfile": "@@rules_rust+//crate_universe:Cargo.lock", + "cargo_toml": "@@rules_rust+//crate_universe:Cargo.toml", + "version": "1.86.0", + "timeout": 900, + "rust_toolchain_cargo_template": "@rust_host_tools//:bin/{tool}", + "rust_toolchain_rustc_template": "@rust_host_tools//:bin/{tool}", + "compressed_windows_toolchain_names": false + } + } + }, + "moduleExtensionMetadata": { + "explicitRootModuleDirectDeps": [ + "cargo_bazel_bootstrap" + ], + "explicitRootModuleDirectDevDeps": [], + "useAllRepos": "NO", + "reproducible": false + } + } } }, - "facts": {} + "facts": {}, + "factsVersions": {} } diff --git a/examples/generated/source_sync/example.pdf b/examples/generated/source_sync/example.pdf index 7d2e502c7929a42384e9a5e3c710cd1bdb308631..55538a7a9665a9a5fd3a84025499b6db85691140 100644 GIT binary patch delta 9495 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 Date: Fri, 28 Aug 2026 07:03:31 -0700 Subject: [PATCH 8/8] Release 0.3.0 Host fonts are no longer searched, so documents that relied on a system font now render with an embedded fallback and every checked-in PDF needs regenerating. --- MODULE.bazel | 2 +- version.bzl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 1c18896..48b5c3f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,7 +2,7 @@ module( name = "rules_typst", - version = "0.2.0", + version = "0.3.0", ) bazel_dep(name = "rules_rust", version = "0.68.1") diff --git a/version.bzl b/version.bzl index eb61696..515293d 100644 --- a/version.bzl +++ b/version.bzl @@ -1,3 +1,3 @@ """"rules_typst version""" -VERSION = "0.2.0" +VERSION = "0.3.0"