├── .bazelignore ├── .bazelversion ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── BUILD.bazel ├── CONTRIBUTING.md ├── COPYING.txt ├── LICENSE.txt ├── MODULE.bazel ├── README.md ├── WORKSPACE ├── WORKSPACE.bzlmod ├── dvi_sub.py ├── example ├── BUILD.bazel ├── bzlmod │ ├── .gitignore │ ├── BUILD.bazel │ ├── MODULE.bazel │ └── my_document.tex ├── bzlmod_use_texlive_deps │ ├── .gitignore │ ├── BUILD.bazel │ ├── MODULE.bazel │ └── my_document.tex ├── chapters │ └── introduction.tex ├── example_class │ ├── BUILD │ └── example_class.cls ├── my_report.tex ├── references.bib ├── test │ ├── BUILD.bazel │ └── test_examples.py └── tikz.tex ├── extensions.bzl ├── latex.bzl ├── latex_engine_cmds.bzl ├── packages ├── BUILD.bazel ├── adjustbox_test.tex ├── algorithm2e_test.tex ├── amsgen_test.tex ├── amsmath_test.tex ├── amssymb_test.tex ├── amstext_test.tex ├── amsthm_test.tex ├── array_test.tex ├── auxhook_test.tex ├── babel_dutch_test.tex ├── babel_english_test.tex ├── beamer_themedefault_test.tex ├── beamer_themesplit_test.tex ├── beamertheme-metropolis_test.tex ├── booktabs_test.tex ├── calc_test.tex ├── capt-of_test.tex ├── caption_test.tex ├── changepage_test.tex ├── cleveref_test.tex ├── collectbox_test.tex ├── color_test.tex ├── colortbl_test.tex ├── contour_test.tex ├── cooking-units_test.tex ├── csquotes_test.tex ├── currfile_test.tex ├── datatool_fp_test.tex ├── datatool_pgfmath_test.tex ├── datenumber_test.tex ├── datetime2_english_test.tex ├── datetime2_test.tex ├── datetime_test.tex ├── drawstack_test.tex ├── enumerate_test.tex ├── enumitem_test.tex ├── environ_test.tex ├── epstopdf-base_test.tex ├── etoolbox_test.tex ├── eufrak_test.tex ├── everyshi_test.tex ├── exam_test.tex ├── expl3_test.tex ├── fancyhdr_test.tex ├── filehook_test.tex ├── filemod_test.tex ├── float_test.tex ├── fmtcount_test.tex ├── fontawesome5_test.tex ├── fontawesome_test.tex ├── fontspec_test.tex ├── fp_test.tex ├── framed_test.tex ├── fullpage_test.tex ├── gensymb_test.tex ├── geometry_test.tex ├── gincltex_test.tex ├── glossaries-extra_test.tex ├── glossaries_test.tex ├── gnuplottex_test.tex ├── graphicx_test.tex ├── grfext_test.tex ├── hanging_test.tex ├── helvet_test.tex ├── hyperref_test.tex ├── hyph_utf8_test.tex ├── hyphenat_test.tex ├── ieeetran_test.tex ├── ifluatex_test.tex ├── ifmtarg_test.tex ├── ifoddpage_test.tex ├── ifpdf_test.tex ├── iftex_test.tex ├── ifthen_test.tex ├── import_test.tex ├── keyval_test.tex ├── koma_script_test.tex ├── kvdefinekeys_test.tex ├── kvoptions_test.tex ├── l3keys2e_test.tex ├── lastpage_test.tex ├── lettrine_test.tex ├── lineno_test.tex ├── listings_test.tex ├── lm_test.tex ├── longtable_test.tex ├── lstautogobble_test.tex ├── ltxcmds_test.tex ├── luacode_test.tex ├── luatex85_test.tex ├── makecell_test.tex ├── marginfix_test.tex ├── marginnote_test.tex ├── marvosym_test.tex ├── mathastext_test.tex ├── mdframed_test.tex ├── mfirstuc_test.tex ├── mflogo_test.tex ├── microtype_test.tex ├── minifp_test.tex ├── mnsymbol_test.tex ├── moderncv_casual_test.tex ├── moderncv_classic_test.tex ├── multicol_test.tex ├── needspace_test.tex ├── nth_test.tex ├── packages.bzl ├── parskip_test.tex ├── pdfcomment_test.tex ├── pgfcore_test.tex ├── pgfopts_test.tex ├── pgfplots_test.tex ├── placeat_test.tex ├── placeins_test.tex ├── ragged2e_test.tex ├── relsize_test.tex ├── silence_test.tex ├── siunitx_test.tex ├── soul_test.tex ├── soulpos_test.tex ├── soulutf8_test.tex ├── standalone_documentclass_test.tex ├── standalone_package_test.tex ├── subcaption_test.tex ├── substr_test.tex ├── svn-prov_test.tex ├── tabularx_test.tex ├── tabulary_test.tex ├── tcolorbox_test.tex ├── textcase_test.tex ├── tgheros_test.tex ├── tikz-qtree_test.tex ├── tikz_test.tex ├── titlesec_test.tex ├── titling_test.tex ├── tocloft_test.tex ├── tracklang_test.tex ├── translations_test.tex ├── translator_test.tex ├── trimspaces_test.tex ├── ulem_test.tex ├── unicode-math_test.tex ├── units_test.tex ├── upquote_test.tex ├── url_test.tex ├── verbatim_test.tex ├── xcharter_test.tex ├── xcolor_test.tex ├── xfor_test.tex ├── xfrac_test.tex ├── xifthen_test.tex ├── xkeyval_test.tex ├── xparse_test.tex ├── xspace_test.tex ├── xstring_test.tex ├── xtemplate_test.tex └── zref-savepos_test.tex ├── patches ├── latexrun-force-colors ├── latexrun-pull-21 ├── latexrun-pull-47 ├── latexrun-pull-52 ├── latexrun-pull-61 └── latexrun-pull-62 ├── repositories.bzl ├── requirements.in ├── requirements_lock.txt ├── texlive_2022_repos.bzl ├── third_party └── BUILD.bazel ├── toolchain.bzl ├── tools └── compute_dependencies │ ├── .gitignore │ └── compute_dependencies.py ├── version.bzl └── view_output.sh /.bazelignore: -------------------------------------------------------------------------------- 1 | example/bzlmod 2 | example/bzlmod_use_texlive_deps -------------------------------------------------------------------------------- /.bazelversion: -------------------------------------------------------------------------------- 1 | 7.3.2 -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | workflow_dispatch: 10 | 11 | jobs: 12 | buildifier: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: thompsonja/bazel-buildifier@v0.4.0 17 | with: 18 | buildifier_version: v7.3.1 19 | warnings: all 20 | 21 | test: 22 | strategy: 23 | matrix: 24 | folder: 25 | - "example" 26 | - "packages" 27 | platform: 28 | - macos-latest 29 | - ubuntu-latest 30 | 31 | runs-on: ${{ matrix.platform }} 32 | 33 | steps: 34 | - uses: actions/checkout@v3 35 | - name: Mount bazel caches 36 | id: bazel_cache 37 | uses: actions/cache@v3 38 | with: 39 | path: | 40 | "~/.cache/bazel" 41 | "~/.cache/bazel-repo" 42 | key: ${{matrix.platform}}-bazel-cache-${{ hashFiles('**/BUILD.bazel', '**/*.bzl', 'WORKSPACE') }} 43 | restore-keys: ${{matrix.platform}}-bazel-cache- 44 | - name: Build ${{ matrix.folder }} 45 | env: 46 | XDG_CACHE_HOME: ~/.cache/bazel-repo 47 | run: | 48 | bazel build //${{ matrix.folder }}:all 49 | - name: Test 50 | if: ${{matrix.folder == 'example'}} 51 | env: 52 | XDG_CACHE_HOME: ~/.cache/bazel-repo 53 | run: | 54 | bazel test //${{ matrix.folder }}/test/... --verbose_failures --test_output=streamed 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .ijwb 3 | .nfs* 4 | /bazel-* 5 | /MODULE.bazel.lock -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_python//python:defs.bzl", "py_binary") 2 | load("@rules_python//python:pip.bzl", "compile_pip_requirements") 3 | load(":toolchain.bzl", "latex_toolchain") 4 | 5 | exports_files([ 6 | "view_output.sh", 7 | ]) 8 | 9 | toolchain_type( 10 | name = "latex_toolchain_type", 11 | visibility = ["//visibility:public"], 12 | ) 13 | 14 | # This toolchain seems to be missing the 'biber' binary, causing Bazel to produce the following error 15 | # "no such target '@@texlive_bin__amd64-freebsd//:biber': target 'biber' not declared in package ''" 16 | # Disabled for now 17 | # latex_toolchain( 18 | # exec_compatible_with = [ 19 | # "@platforms//cpu:x86_64", 20 | # "@platforms//os:freebsd", 21 | # ], 22 | # platform = "amd64-freebsd", 23 | # ) 24 | 25 | latex_toolchain( 26 | name = "latex_toolchain_aarch64-darwin", 27 | exec_compatible_with = [ 28 | "@platforms//cpu:aarch64", 29 | "@platforms//os:osx", 30 | ], 31 | platform = "universal-darwin", 32 | ) 33 | 34 | latex_toolchain( 35 | name = "latex_toolchain_x86_64-darwin", 36 | exec_compatible_with = [ 37 | "@platforms//cpu:x86_64", 38 | "@platforms//os:osx", 39 | ], 40 | platform = "universal-darwin", 41 | ) 42 | 43 | latex_toolchain( 44 | exec_compatible_with = [ 45 | "@platforms//cpu:x86_64", 46 | "@platforms//os:linux", 47 | ], 48 | platform = "x86_64-linux", 49 | ) 50 | 51 | filegroup( 52 | name = "core_dependencies", 53 | srcs = [ 54 | "@bazel_latex_texlive//:texlive_extra__tlpkg__TeXLive", 55 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__base", 56 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__cm-super", 57 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__lm", 58 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__lm", 59 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__cm", 60 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__latex-fonts", 61 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__lm", 62 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__amsfonts__cm", 63 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__cm-super", 64 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__lm", 65 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__scripts__texlive", 66 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__config", 67 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__hyphen", 68 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__iftex", 69 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__infwarerr", 70 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__kvsetkeys", 71 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__ltxcmds", 72 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__pdftexcmds", 73 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__unicode-data", 74 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__base", 75 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__kvoptions", 76 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3backend", 77 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3kernel", 78 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__xparse", 79 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__latexconfig", 80 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lm", 81 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__luatex__lua-uni-algos", 82 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__luatex__lualibs", 83 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__luatex__luaotfload", 84 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__web2c", 85 | ], 86 | visibility = ["//visibility:public"], 87 | ) 88 | 89 | filegroup( 90 | name = "ghostscript_dependencies", 91 | srcs = [ 92 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__dvips__base", 93 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__dvips__l3backend", 94 | ], 95 | visibility = ["//visibility:public"], 96 | ) 97 | 98 | py_binary( 99 | name = "dvi_sub", 100 | srcs = ["dvi_sub.py"], 101 | visibility = ["//visibility:public"], 102 | ) 103 | 104 | compile_pip_requirements( 105 | name = "requirements", 106 | src = "requirements.in", 107 | requirements_txt = "requirements_lock.txt", 108 | tags = ["manual"], 109 | ) 110 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute to Bazel LaTeX 2 | 3 | ## Bugs 4 | 5 | #### Did you find a bug? 6 | Ensure the bug was not already reported by searching the open and closed issues. 7 | 8 | If you are unable to find an issue addressing the problem, then open a new one. Make sure to include a title, clear description, and as much relevant information as possible. 9 | 10 | #### Did you fix a bug? 11 | Open a new pull request with your fix. Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. 12 | 13 | ## Features 14 | 15 | #### Do you intend to add a new feature or change an existing one? 16 | Suggest your change by opening an issue. 17 | 18 | #### Do you want to expose another TeX Live package? 19 | If the desired package to use is not available through bazel-latex, but it is available in TeX Live, then it is possible to patch `BUILD.bazel` to add support for the desired packages locally. 20 | 21 | If that does not suffice, please feel free to open a PR adding the package to `/packages/BUILD.bazel`, including proper tests. 22 | 23 | ## Questions 24 | 25 | #### Do you have questions about the source code or usage? 26 | Ask any question about how to use Bazel LaTeX by opening a blank issue. 27 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright 2018 Prodrive Technologies B.V. 2 | Copyright 2018 Google LLC. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | """ 2 | Rules for building LaTeX documents with Bazel. 3 | """ 4 | 5 | module( 6 | name = "bazel_latex", 7 | version = "1.2.2", 8 | compatibility_level = 0, 9 | repo_name = "bazel_latex", 10 | ) 11 | 12 | bazel_dep(name = "platforms", version = "0.0.10") 13 | bazel_dep(name = "rules_foreign_cc", version = "0.12.0") 14 | bazel_dep(name = "rules_python", version = "0.36.0") 15 | 16 | pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") 17 | pip.parse( 18 | hub_name = "py_deps", 19 | python_version = "3.11", 20 | requirements_lock = "//:requirements_lock.txt", 21 | ) 22 | use_repo(pip, "py_deps") 23 | 24 | register_toolchains( 25 | "//:latex_toolchain_aarch64-darwin", 26 | # The latex_toolchain_amd64-freebsd seems broken, see comment in BUILD.bazel, so disabled for now 27 | #"@bazel_latex//:latex_toolchain_amd64-freebsd", 28 | "//:latex_toolchain_x86_64-darwin", 29 | "//:latex_toolchain_x86_64-linux", 30 | ) 31 | 32 | texlive_repositories = use_extension("//:extensions.bzl", "texlive_repositories") 33 | texlive_repositories.install() 34 | use_repo( 35 | texlive_repositories, 36 | "bazel_latex_texlive", 37 | "texlive_bin__aarch64-linux", 38 | "texlive_bin__amd64-freebsd", 39 | "texlive_bin__amd64-netbsd", 40 | "texlive_bin__armhf-linux", 41 | "texlive_bin__i386-cygwin", 42 | "texlive_bin__i386-freebsd", 43 | "texlive_bin__i386-linux", 44 | "texlive_bin__i386-netbsd", 45 | "texlive_bin__i386-solaris", 46 | "texlive_bin__universal-darwin", 47 | "texlive_bin__win32", 48 | "texlive_bin__x86_64-cygwin", 49 | "texlive_bin__x86_64-darwinlegacy", 50 | "texlive_bin__x86_64-linux", 51 | "texlive_bin__x86_64-linuxmusl", 52 | "texlive_bin__x86_64-solaris", 53 | "texlive_texmf__texmf-dist__scripts__texlive", 54 | ) 55 | 56 | module_repositories = use_extension("//:repositories.bzl", "module_repositories") 57 | use_repo( 58 | module_repositories, 59 | "bazel_latex_latexrun", 60 | "ghost_script_source", 61 | ) 62 | 63 | # macOS shared lib was difficult to build via foreign rules so as a temporary 64 | # solution we provide it as a precompiled artifact. 65 | # Consider making it available via bazel_latex binaries repo instead 66 | http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 67 | 68 | http_archive( 69 | name = "ghostscript_macos", 70 | build_file_content = """ 71 | filegroup( 72 | name = "libgs_macos", 73 | srcs = glob(["*/*"]), 74 | target_compatible_with = ["@platforms//os:osx"], 75 | visibility = ["//visibility:public"], 76 | ) 77 | """, 78 | sha256 = "56b480ebdf34000eac4a29e108ce6384858941d892fd69e604d90585aaae4c94", 79 | urls = [ 80 | "https://github.com/solsjo/rules_latex_deps/releases/download/v0.9.4/rules_latex_deps_macos-latest.zip", 81 | ], 82 | ) 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bazel rules for LaTeX 2 | 3 | This repository provides [Bazel](https://bazel.build/) rules for LaTeX, 4 | inspired by [Klaus Aehlig's blog post](http://www.linta.de/~aehlig/techblog/2017-02-19.html) 5 | on the matter. 6 | 7 | Instead of depending on the host system's copy of LaTeX, these rules 8 | download [a modular copy of TeXLive from GitHub](https://github.com/ProdriveTechnologies/texlive-modular). 9 | By using fine-grained dependencies, you will only download portions of 10 | TeXLive that are actually used in your documents. 11 | 12 | As the output of the LaTeX tools is unnecessarily verbose, the main build 13 | rules invoke LaTeX using [latexrun](https://github.com/aclements/latexrun). 14 | Errors and warnings are formatted similar to those generated by Clang. 15 | 16 | BibLaTeX is supported by biber and bibtex. Both are obtained from the 17 | TeX Live distribution. Latexrun defaults to bibtex. Please specify the 18 | command flag mentioned below to build with biber instead. 19 | 20 | # Using these rules 21 | 22 | ## Traditional workspace approach 23 | 24 | Add the following to `WORKSPACE`: 25 | 26 | ```python 27 | http_archive( 28 | name = "bazel_latex", 29 | sha256 = "", 30 | strip_prefix = "bazel-latex-", 31 | url = "https://github.com/ProdriveTechnologies/bazel-latex/archive/v.tar.gz", 32 | patches = ["some_patch.patch"], % Optional 33 | ) 34 | 35 | load("@bazel_latex//:repositories.bzl", "latex_repositories") 36 | 37 | latex_repositories() 38 | 39 | # Needed for building ghostscript 40 | # Which is needed by dvisvgm, 41 | # dvisvgm is part of the texlive toolchain, 42 | # but cannot produce correct svg from pdf files without dynamically 43 | # linking to ghostscript. 44 | load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") 45 | 46 | rules_foreign_cc_dependencies() 47 | 48 | # mac os shared lib was cumbersome to build via foreign rules so as a temporary 49 | # solution we provide it as a precompiled artifact. 50 | # Consider making it available via bazel_latex binaries repo instead 51 | http_archive( 52 | name = "ghostscript_macos", 53 | build_file_content = """ 54 | filegroup( 55 | name = "libgs_macos", 56 | srcs = glob(["*/*"]), 57 | target_compatible_with = ["@platforms//os:osx"], 58 | visibility = ["//visibility:public"], 59 | ) 60 | """, 61 | sha256 = "56b480ebdf34000eac4a29e108ce6384858941d892fd69e604d90585aaae4c94", 62 | urls = [ 63 | "https://github.com/solsjo/rules_latex_deps/releases/download/v0.9.4/rules_latex_deps_macos-latest.zip", 64 | ], 65 | ) 66 | ``` 67 | 68 | ## Using Bzlmod 69 | 70 | Add to your `MODULE.bazel` file: 71 | 72 | ```python 73 | bazel_dep(name = "bazel_latex") 74 | 75 | git_override( 76 | module_name = "bazel_latex", 77 | remote = "https://github.com/ProdriveTechnologies/bazel-latex.git", 78 | commit = "227b02f346c1dd0098d32b5bcb1ef874dd367e2a", 79 | ) 80 | ``` 81 | 82 | ## Build files 83 | 84 | And add the following `load()` directive to your `BUILD` files: 85 | 86 | ```python 87 | load("@bazel_latex//:latex.bzl", "latex_document") 88 | ``` 89 | 90 | You can then use `latex_document()` in `BUILD` file to declare documents that 91 | need to be built. 92 | 93 | ```python 94 | load("@bazel_latex//:latex.bzl", "latex_document", "latex_to_svg") 95 | 96 | latex_document( 97 | name = "my_report", 98 | srcs = glob([ 99 | "chapters/*.tex", 100 | ]) + [ 101 | "@bazel_latex//packages:biblatex", 102 | "references.bib", 103 | "//example/example_class:example_class", 104 | ], 105 | bib_tool = "biber", # Is the default 106 | format = "pdf", # Is the default 107 | main = "my_report.tex", 108 | ) 109 | 110 | latex_to_svg( 111 | name = "my_svg_report", 112 | src = ":my_report", 113 | libgs = select({ 114 | "@platforms//os:osx": "@ghostscript_macos//:libgs_macos", 115 | "//conditions:default": "@bazel_latex//third_party:libgs", 116 | }), 117 | ) 118 | 119 | latex_document( 120 | name = "my_dvi_report", 121 | srcs = glob([ 122 | "chapters/*.tex", 123 | ]) + [ 124 | "@bazel_latex//packages:biblatex", 125 | "references.bib", 126 | "//example/example_class:example_class", 127 | ], 128 | format = "dvi", 129 | main = "my_report.tex", 130 | ) 131 | 132 | # svgs generated from dvis are 'searchable'. 133 | # This is not yet the case for svg generated from pdfs. 134 | latex_to_svg( 135 | name = "my_dvi_svg_report", 136 | src = ":my_dvi_report", 137 | ) 138 | ``` 139 | 140 | Note: For OS X, ghostscript for OS X might not be binary compatible with your 141 | version of OS X, as it is provided as a precompiled artifact. 142 | 143 | Note: For OS X, latex_to_svg makes use of python to find the absolute path 144 | of ghostscript. In using python it also assumes that python3 on OS X is located 145 | at /usr/local/bin. This is unfortunate, but can be fixed in a later release. 146 | 147 | 148 | Utilize `cmd_flags` to provide optional command line arguments. 149 | 150 | Commonly reused sources (e.g., templates) can be placed in 151 | [`filegroup()`](https://docs.bazel.build/versions/master/be/general.html#filegroup) 152 | blocks, so that they don't need to be repeated. Those `filegroup()` could 153 | be located not just in the single `BUILD` file, but in any of sub directories. 154 | For example, if you want to include company specific template files which are 155 | located in `//company_dir` directory as `company_style`, then declare them as 156 | like following in `company_dir/BUILD` file, and include the dependency, like 157 | `//company_dir:company_style`, in `latex_repositories`. 158 | 159 | ```python 160 | filegroup( 161 | name = "company_style", 162 | srcs = glob([ 163 | ... 164 | ]), 165 | ) 166 | ``` 167 | 168 | A PDF can be built by running: 169 | 170 | ``` 171 | bazel build //example:my_report 172 | ``` 173 | 174 | It can be viewed using your system's PDF viewer by running: 175 | 176 | ``` 177 | bazel run //example:my_report_view 178 | ``` 179 | 180 | If you want to get the output from the PDF viewer you can run: 181 | 182 | ``` 183 | bazel run //example:my_report_view_output 184 | ``` 185 | 186 | # Using packages 187 | 188 | By default, `latex_document()` only provides a version of TeXLive that 189 | is complete enough to build the most basic documents. Whenever you use 190 | `\usepackage{}` in your documents, you must also add a corresponding 191 | dependency to your `latex_document()`. This will cause Bazel to download 192 | and expose those packages for you. Below is an example of how a document 193 | can be built that depends on the Hyperref package. 194 | 195 | ```python 196 | latex_document( 197 | name = "hello", 198 | srcs = ["@bazel_latex//packages:hyperref"], 199 | main = "hello.tex", 200 | ) 201 | ``` 202 | 203 | This repository provides bindings for most commonly used packages. 204 | Please open a pull request if additional bindings are needed. 205 | 206 | ## Local packages 207 | If the desired package to use is not available through bazel-latex, but is 208 | available in TeX Live, then it is possible to patch `BUILD.bazel` in 209 | `/packages` to add support for the desired package locally. 210 | 211 | Therefore, clone bazel-latex locally, and make the desired changes to the 212 | packages build file. Then, put the output of the diff in `some_patch.patch`, 213 | and update your `WORKSPACE` accordingly as shown below. 214 | 215 | ```python 216 | http_archive( 217 | name = "bazel_latex", 218 | sha256 = "", 219 | strip_prefix = "bazel-latex-", 220 | url = "https://github.com/ProdriveTechnologies/bazel-latex/archive/v.tar.gz", 221 | patches = ["some_patch.patch"], 222 | ) 223 | ``` 224 | 225 | If this solution does not suffice, please feel free to open a PR to add the 226 | corresponding package to Bazel LaTeX. In that case, also see `CONTRIBUTING.md`. 227 | 228 | # Example 229 | 230 | An example is available in the corresponding folder. The example can 231 | be executed by running: 232 | ``` 233 | bazel run //example:my_report_view 234 | ``` 235 | 236 | # Platform support 237 | 238 | These rules have been tested to work on (using bazel 3.2.0): 239 | 240 | - FreeBSD 11.2, building locally. 241 | - macOS Mojave 10.14, building locally. 242 | - macOS Catalina 10.15, building locally. 243 | - Ubuntu 18.04, building locally. 244 | - Ubuntu 18.04 WSL, building locally. 245 | - Ubuntu 18.04, building on a Debian 8 based 246 | [Buildbarn](https://github.com/buildbarn) setup. 247 | - Ubuntu 19.04 (Disco Dingo), building locally. 248 | - Ubuntu 20.04, building locally. 249 | - Ubuntu 22.04, github actions 250 | - Manjaro 18.1.2 (Juhraya), building locally. 251 | - Windows 10 1803, building on a Debian 8 based 252 | [Buildbarn](https://github.com/buildbarn) setup. 253 | 254 | These rules are known not to work on: 255 | 256 | - Windows (paths are unix-style) should be fixed in a PR. 257 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "bazel_latex") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4 | 5 | http_archive( 6 | name = "bazel_toolchains", 7 | sha256 = "109a99384f9d08f9e75136d218ebaebc68cc810c56897aea2224c57932052d30", 8 | strip_prefix = "bazel-toolchains-94d31935a2c94fe7e7c7379a0f3393e181928ff7", 9 | urls = [ 10 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/94d31935a2c94fe7e7c7379a0f3393e181928ff7.tar.gz", 11 | "https://github.com/bazelbuild/bazel-toolchains/archive/94d31935a2c94fe7e7c7379a0f3393e181928ff7.tar.gz", 12 | ], 13 | ) 14 | 15 | register_toolchains( 16 | "@bazel_latex//:latex_toolchain_aarch64-darwin", 17 | # The latex_toolchain_amd64-freebsd seems broken, see comment in BUILD.bazel, so disabled for now 18 | #"@bazel_latex//:latex_toolchain_amd64-freebsd", 19 | "@bazel_latex//:latex_toolchain_x86_64-darwin", 20 | "@bazel_latex//:latex_toolchain_x86_64-linux", 21 | ) 22 | 23 | load("@bazel_latex//:repositories.bzl", "latex_repositories") 24 | 25 | latex_repositories() 26 | 27 | # Needed for building ghostscript 28 | # Which is needed by dvisvgm, 29 | # dvisvgm is part of the texlive toolchain, 30 | # but cannot produce correct svg files without dynamically 31 | # linking to ghostscript. 32 | load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") 33 | 34 | rules_foreign_cc_dependencies() 35 | 36 | # mac os shared lib was difficult to build via foreign rules so as a temporary 37 | # solution we provide it as a precompiled artifact. 38 | # Consider making it available via bazel_latex binaries repo instead 39 | http_archive( 40 | name = "ghostscript_macos", 41 | build_file_content = """ 42 | filegroup( 43 | name = "libgs_macos", 44 | srcs = glob(["*/*"]), 45 | target_compatible_with = ["@platforms//os:osx"], 46 | visibility = ["//visibility:public"], 47 | ) 48 | """, 49 | sha256 = "56b480ebdf34000eac4a29e108ce6384858941d892fd69e604d90585aaae4c94", 50 | urls = [ 51 | "https://github.com/solsjo/rules_latex_deps/releases/download/v0.9.4/rules_latex_deps_macos-latest.zip", 52 | ], 53 | ) 54 | 55 | http_archive( 56 | name = "rules_python", 57 | sha256 = "ca77768989a7f311186a29747e3e95c936a41dffac779aff6b443db22290d913", 58 | strip_prefix = "rules_python-0.36.0", 59 | url = "https://github.com/bazelbuild/rules_python/archive/0.36.0.tar.gz", 60 | ) 61 | 62 | load("@rules_python//python:repositories.bzl", "py_repositories") 63 | 64 | py_repositories() 65 | 66 | load("@rules_python//python:pip.bzl", "pip_parse") 67 | 68 | pip_parse( 69 | name = "py_deps", 70 | requirements_lock = "//:requirements_lock.txt", 71 | ) 72 | 73 | load("@py_deps//:requirements.bzl", "install_deps") 74 | 75 | install_deps() 76 | -------------------------------------------------------------------------------- /WORKSPACE.bzlmod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProdriveTechnologies/bazel-latex/c552d5bd09e4e9e49040ede60dd97720acb1cbb7/WORKSPACE.bzlmod -------------------------------------------------------------------------------- /dvi_sub.py: -------------------------------------------------------------------------------- 1 | """ Replace absolute font paths with relative paths in dvi files. 2 | 3 | The absolute font paths point back into the prevous sandbox 4 | in which the dvi was created. 5 | Resulting in problems finding the font in e.g. svg grneration. 6 | 7 | By using relative paths we make sure that, at least in our Bazel workflow, 8 | font can referenced. 9 | """ 10 | 11 | import argparse 12 | import re 13 | 14 | 15 | def parse_args(): 16 | parser = argparse.ArgumentParser() 17 | parser.add_argument("in_file") 18 | parser.add_argument("out_file") 19 | args = parser.parse_args() 20 | return args 21 | 22 | 23 | def sub(in_file, out_file): 24 | with open(in_file, 'rb') as fd: 25 | old_data = fd.read() 26 | # TODO: This function could be parameterized 27 | # in respect to font type and regex pattern 28 | path_root_pattern = re.compile(b"\[(.*?)external") 29 | ext_pattern = re.compile(b"\[.*\.(.*?)]") 30 | result = path_root_pattern.findall(old_data) 31 | unique_ext = set(ext_pattern.findall(old_data)) 32 | if result and unique_ext: 33 | sub_string = result[0] 34 | short_data = re.sub(sub_string, b'./', old_data) 35 | path_len_diff = len(sub_string) - len(b'./') 36 | new_data = short_data 37 | for ext in unique_ext: 38 | new_data = re.sub( 39 | b'\.' + ext+ b']', 40 | b'.' + ext + (b'\x00' * path_len_diff) + b']', 41 | new_data 42 | ) 43 | assert len(old_data) == len(new_data), f"{len(old_data)} {len(new_data)}" 44 | else: 45 | new_data = old_data 46 | with open(out_file, 'wb') as fd: 47 | fd.write(new_data) 48 | 49 | 50 | def main(): 51 | args = parse_args() 52 | sub(args.in_file, args.out_file) 53 | 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /example/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_latex//:latex.bzl", "latex_document", "latex_to_svg") 2 | 3 | exports_files(["my_report.tex"]) 4 | 5 | latex_document( 6 | name = "my_report", 7 | srcs = glob([ 8 | "chapters/*.tex", 9 | ]) + [ 10 | "references.bib", 11 | "//example/example_class", 12 | "@bazel_latex//packages:biblatex", 13 | ], 14 | bib_tool = "biber", # Is the default 15 | main = "my_report.tex", 16 | visibility = ["//visibility:public"], 17 | ) 18 | 19 | latex_document( 20 | name = "my_dvi_report", 21 | srcs = glob([ 22 | "chapters/*.tex", 23 | ]) + [ 24 | "references.bib", 25 | "//example/example_class", 26 | "@bazel_latex//packages:biblatex", 27 | ], 28 | format = "dvi", 29 | main = "my_report.tex", 30 | ) 31 | 32 | latex_to_svg( 33 | name = "my_svg_report_from_dvi", 34 | src = ":my_dvi_report", 35 | args = [ 36 | "--font-format=woff,autohint", 37 | "--optimize", 38 | ], 39 | visibility = ["//visibility:public"], 40 | ) 41 | 42 | # NOTE: svgs generated from pdfs are not searchable until dvisvgm 43 | # version 3.0 using a separate helper tool mutool. 44 | # Also, libgs is only required when generating svgs from pdfs. 45 | latex_to_svg( 46 | name = "my_svg_report_from_pdf", 47 | src = ":my_report", 48 | libgs = select({ 49 | "@platforms//os:osx": "@ghostscript_macos//:libgs_macos", 50 | "//conditions:default": "@bazel_latex//third_party:libgs", 51 | }), 52 | visibility = ["//visibility:public"], 53 | ) 54 | 55 | latex_document( 56 | name = "my_standalone_figure", 57 | srcs = ["@bazel_latex//packages:drawstack"], 58 | format = "dvi", 59 | main = "tikz.tex", 60 | ) 61 | 62 | latex_to_svg( 63 | name = "example_svg", 64 | src = ":my_standalone_figure", 65 | args = ["-e"], 66 | ) 67 | -------------------------------------------------------------------------------- /example/bzlmod/.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | /MODULE.bazel.lock -------------------------------------------------------------------------------- /example/bzlmod/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_latex//:latex.bzl", "latex_document") 2 | 3 | latex_document( 4 | name = "my_document", 5 | srcs = [], 6 | main = "my_document.tex", 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /example/bzlmod/MODULE.bazel: -------------------------------------------------------------------------------- 1 | """ 2 | Simple bzlmod example 3 | """ 4 | 5 | module( 6 | name = "bazel_latex_example_bzlmod", 7 | ) 8 | 9 | bazel_dep(name = "bazel_latex") 10 | local_path_override( 11 | module_name = "bazel_latex", 12 | path = "../..", 13 | ) 14 | -------------------------------------------------------------------------------- /example/bzlmod/my_document.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \begin{document} 3 | \section{Hello world} 4 | Test 5 | \end{document} 6 | -------------------------------------------------------------------------------- /example/bzlmod_use_texlive_deps/.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | /MODULE.bazel.lock -------------------------------------------------------------------------------- /example/bzlmod_use_texlive_deps/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_latex//:latex.bzl", "latex_document") 2 | 3 | latex_document( 4 | name = "my_document", 5 | srcs = [ 6 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__multirow", 7 | ], 8 | main = "my_document.tex", 9 | visibility = ["//visibility:public"], 10 | ) 11 | -------------------------------------------------------------------------------- /example/bzlmod_use_texlive_deps/MODULE.bazel: -------------------------------------------------------------------------------- 1 | """ 2 | Simple example that shows how to import the 'bazel_latex_texlive' proxy 3 | """ 4 | 5 | module( 6 | name = "bazel_latex_example_bzlmod_use_texlive_deps", 7 | ) 8 | 9 | bazel_dep(name = "bazel_latex") 10 | local_path_override( 11 | module_name = "bazel_latex", 12 | path = "../..", 13 | ) 14 | 15 | texlive_repositories = use_extension("@bazel_latex//:extensions.bzl", "texlive_repositories") 16 | texlive_repositories.install() 17 | use_repo( 18 | texlive_repositories, 19 | "bazel_latex_texlive", 20 | ) 21 | -------------------------------------------------------------------------------- /example/bzlmod_use_texlive_deps/my_document.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{multirow} 3 | \begin{document} 4 | \begin{tabular}{|c|c|} 5 | \multirow{2}{*}{1}\\ 6 | \end{tabular} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /example/chapters/introduction.tex: -------------------------------------------------------------------------------- 1 | This is an example PDF generated by ProdriveTechnologies/bazel-latex~\cite{github}. 2 | -------------------------------------------------------------------------------- /example/example_class/BUILD: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "example_class", 3 | srcs = [ 4 | "example_class.cls", 5 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xcolor", 6 | ], 7 | visibility = ["//visibility:public"], 8 | ) 9 | -------------------------------------------------------------------------------- /example/example_class/example_class.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e} 2 | \ProvidesClass{example_class} 3 | 4 | \newcommand{\headlinecolor}{\normalcolor} 5 | \LoadClass[onecolumn]{article} 6 | -------------------------------------------------------------------------------- /example/my_report.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper]{example_class} 2 | 3 | \usepackage[backend=biber]{biblatex} 4 | \addbibresource{example/references.bib} 5 | 6 | \title{Bazel rules for LaTex example} 7 | \author{Prodrive Technologies} 8 | \date{2019-11-13} 9 | 10 | \begin{document} 11 | \maketitle 12 | \input{example/chapters/introduction} 13 | \printbibliography 14 | \end{document} 15 | -------------------------------------------------------------------------------- /example/references.bib: -------------------------------------------------------------------------------- 1 | @online{github, 2 | title = {Bazel rules for LaTeX}, 3 | organization = {Prodrive Technologies}, 4 | date = {2018}, 5 | urldate = {2020-07-10}, 6 | url = {https://github.com/ProdriveTechnologies/bazel-latex}, 7 | keywords = {trusted}, 8 | } 9 | -------------------------------------------------------------------------------- /example/test/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@py_deps//:requirements.bzl", "requirement") 2 | load("@rules_python//python:defs.bzl", "py_test") 3 | 4 | filegroup( 5 | name = "rule_output", 6 | srcs = [ 7 | "@bazel_latex//example:my_report", 8 | "@bazel_latex//example:my_svg_report_from_dvi", 9 | "@bazel_latex//example:my_svg_report_from_pdf", 10 | ], 11 | ) 12 | 13 | py_test( 14 | name = "test_examples", 15 | srcs = ["test_examples.py"], 16 | data = [ 17 | ":rule_output", 18 | "@bazel_latex//example:my_report.tex", 19 | ], 20 | deps = [ 21 | requirement("beautifulsoup4"), 22 | requirement("lxml"), 23 | requirement("pypdf"), 24 | requirement("reportlab"), 25 | requirement("svglib"), 26 | ], 27 | ) 28 | -------------------------------------------------------------------------------- /example/test/test_examples.py: -------------------------------------------------------------------------------- 1 | """A tiny example binary for the native Python rules of Bazel.""" 2 | import unittest 3 | import re 4 | 5 | import lxml 6 | import pypdf 7 | 8 | from bs4 import BeautifulSoup 9 | 10 | from reportlab.graphics import renderPDF 11 | from svglib.svglib import svg2rlg 12 | 13 | 14 | def verify_against_my_report_tex(gen_text): 15 | with open("./example/my_report.tex") as fd: 16 | ref_text = fd.read() 17 | 18 | title = re.findall(r"\\title\{([a-zA-Z0-9 \-]*)\}", ref_text, re.MULTILINE)[0].replace(" ", "") 19 | author = re.findall(r"\\author\{([a-zA-Z0-9 \-]*)\}", ref_text, re.MULTILINE)[0].replace(" ", "") 20 | date = re.findall(r"\\date\{([a-zA-Z0-9 \-]*)\}", ref_text, re.MULTILINE)[0].replace(" ", "") 21 | 22 | assert title in gen_text, [ref_text, gen_text] 23 | assert author in gen_text, [ref_text, gen_text] 24 | assert date in gen_text, [ref_text, gen_text] 25 | 26 | 27 | def extract_and_verify(in_file): 28 | with open(in_file) as fd: 29 | gen_data = fd.read() 30 | soup = BeautifulSoup(gen_data, 'xml') 31 | 32 | text_items = soup.find_all('text') 33 | text =[] 34 | for item in text_items: 35 | text.append(item.text) 36 | text = "\n".join(text) 37 | verify_against_my_report_tex(text) 38 | drawing = svg2rlg(in_file) 39 | renderPDF.drawToFile(drawing, "my_pdf_report.pdf") 40 | reader = pypdf.PdfReader("my_pdf_report.pdf") 41 | number_of_pages = len(reader.pages) 42 | page = reader.pages[0] 43 | gen_text = page.extract_text() 44 | gen_text = gen_text.replace(" ","").replace("\n", "") 45 | verify_against_my_report_tex(gen_text) 46 | 47 | 48 | class TestGetNumber(unittest.TestCase): 49 | 50 | def test_pdf(self): 51 | reader = pypdf.PdfReader("./example/my_report.pdf") 52 | number_of_pages = len(reader.pages) 53 | page = reader.pages[0] 54 | gen_text = page.extract_text() 55 | gen_text = gen_text.replace(" ","").replace("\n", "") 56 | verify_against_my_report_tex(gen_text) 57 | 58 | # dvisvgm doesn't support text object in svg from pdf until version 3.0 59 | @unittest.expectedFailure 60 | def test_pdf_svg(self): 61 | extract_and_verify("./example/my_svg_report_from_pdf_svg/my_svg_report_from_pdf_svg-1.svg") 62 | 63 | def test_dvi_svg(self): 64 | extract_and_verify("./example/my_svg_report_from_dvi_svg/my_svg_report_from_dvi_svg-1.svg") 65 | 66 | if __name__ == '__main__': 67 | unittest.main() 68 | -------------------------------------------------------------------------------- /example/tikz.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture} 5 | 6 | \draw (-2,0) -- (2,0); 7 | \filldraw [gray] (0,0) circle (2pt); 8 | \draw (-2,-2) .. controls (0,0) .. (2,-2); 9 | \draw (-2,2) .. controls (-1,0) and (1,0) .. (2,2); 10 | 11 | \end{tikzpicture} 12 | \end{document} 13 | -------------------------------------------------------------------------------- /extensions.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | Extensions for fetching texlive packages 3 | """ 4 | 5 | load("@bazel_latex//:repositories.bzl", "latex_texlive_repositories") 6 | load( 7 | "@bazel_latex//:texlive_2022_repos.bzl", 8 | "TEXLIVE_VERSION_2022", 9 | ) 10 | 11 | def _texlive_repositories_impl(mctx): 12 | for install in mctx.modules[0].tags.install: 13 | latex_texlive_repositories(install.version) 14 | return mctx.extension_metadata(reproducible = True) 15 | 16 | texlive_repositories = module_extension( 17 | implementation = _texlive_repositories_impl, 18 | tag_classes = {"install": tag_class(attrs = {"version": attr.string(default = TEXLIVE_VERSION_2022)})}, 19 | ) 20 | -------------------------------------------------------------------------------- /latex.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | Rules to compile LaTeX documents. 3 | """ 4 | 5 | load("@bazel_latex//:latex_engine_cmds.bzl", "lualatex_engine_cmd_gen") 6 | 7 | LatexOutputInfo = provider( 8 | "Information about the result of a LaTeX compilation.", 9 | fields = { 10 | "deps": "depset of files the document depends on", 11 | "file": "string, e.g. 'foo/bar.pdf'", 12 | "format": "string, e.g. 'pdf'", 13 | }, 14 | ) 15 | 16 | def get_env(ctx, toolchain, files): 17 | """ 18 | Set up environment variables common for all commands. 19 | 20 | Latex and a set of scripts and binaries in the tool suite 21 | makes use of a library, kpathsea. 22 | In general latex distributions are encouraged to follow the 'TDS' 23 | structure. And tools and script might make assumptions that the 24 | layout of directories respects that structure. 25 | 26 | But from our perspective, trying to shoehorn the partioned 27 | repositories according 28 | (E.g. /bazel-latex/external//) 29 | to the TDS creates an unnecessary complexity. 30 | Also kpathsea tries to be efficient about looking up files. 31 | So to derive if a folder is of interest, kpathsea checks if the number 32 | of files or folders in the current folder being inspected is greater 33 | than 2. 34 | Unfortunately symlinks are (currently) not counted. And Bazel makes heavy 35 | use of symlinks. 36 | 37 | However, kpathsea makes heavy use of environment variables (and 38 | ls-R database, IIRC). 39 | So we can work around this limitation. Also, by only adding the 40 | search paths of the files mapped to the environment variable we can reduce 41 | the search space, and reduce build times. 42 | https://tug.org/texinfohtml/kpathsea.html#Supported-file-formats, 43 | lists all environment variables one can set. 44 | 45 | Args: 46 | ctx: For accessing the inputs parameters. 47 | toolchain: The latex toolchain. 48 | files: all files that might be needed as part of the build. 49 | 50 | Returns: 51 | A list of commands to provide to the ctx.actions.run invocation 52 | """ 53 | 54 | def list_unique_folders_from_file_ext(files, exts): 55 | directories = [] 56 | for inp in files: 57 | dirname = inp.dirname 58 | valid = False 59 | if not exts: 60 | valid = True 61 | else: 62 | for ext in exts: 63 | if inp.path.endswith(ext): 64 | valid = True 65 | if valid and dirname not in directories: 66 | directories.append(dirname) 67 | return directories 68 | 69 | def setup_env_for( 70 | type_env_dict, 71 | env_var, 72 | files, 73 | extensions = [], 74 | post_additions = ""): 75 | search_folders = list_unique_folders_from_file_ext( 76 | files, 77 | extensions, 78 | ) 79 | type_env_dict[env_var] = ".:{}{}".format( 80 | ":".join(search_folders), 81 | post_additions, 82 | ) 83 | 84 | type_env = {} 85 | setup_env_for(type_env, "AFMFONTS", files, [".afm"]) 86 | setup_env_for(type_env, "BIBINPUTS", files, [".bib"]) 87 | setup_env_for(type_env, "ENCFONTS", files, [".enc"]) 88 | setup_env_for( 89 | type_env, 90 | "LUAINPUTS", 91 | files, 92 | [".lua" or ".luc"], 93 | ":$TEXINPUTS:", 94 | ) 95 | setup_env_for(type_env, "OPENTYPEFONTS", files) 96 | setup_env_for(type_env, "T1FONTS", files, [".pfa", ".pfb"]) 97 | setup_env_for(type_env, "TEXFONTMAPS", files, [".map"], ":") 98 | setup_env_for(type_env, "TEXINPUTS", files) 99 | setup_env_for(type_env, "TEXPSHEADERS", files, [".pro"]) 100 | setup_env_for(type_env, "TFMFONTS", files, [".tfm"]) 101 | setup_env_for(type_env, "TTFONTS", files, [".ttf", ".ttc"]) 102 | setup_env_for(type_env, "VFFONTS", files, [".vf"]) 103 | 104 | env = { 105 | "PATH": ":".join( 106 | [ 107 | toolchain.kpsewhich.files.to_list()[0].dirname, # latex bin folder 108 | toolchain.mktexlsr.files.to_list()[0].dirname, # script folder 109 | "/bin", # sed, rm, etc. needed by mktexlsr 110 | "/usr/bin", # needed to find python 111 | # NOTE: ctx.configuration.default_shell_env returns {} 112 | # So the default shell env provided by bazel can't 113 | # be updated by the rules. 114 | # Supplying the env argument overwrites bazel's env 115 | # resulting in python not being found. 116 | ], 117 | ), 118 | "SOURCE_DATE_EPOCH": "0", 119 | "TEXMF": ".", 120 | "TEXMFCNF": ctx.files.web2c[0].dirname, 121 | "TEXMFDBS": ".:$TEXMFHOME:$TEXMF", 122 | "TEXMFHOME": ".", 123 | "TEXMFROOT": ".", 124 | } 125 | env.update(type_env) 126 | return env 127 | 128 | def get_engine_cmds_gen(engine_progname): 129 | engine_map = {"lualatex": lualatex_engine_cmd_gen} 130 | return engine_map[engine_progname] 131 | 132 | def _latex_impl(ctx): 133 | toolchain = ctx.toolchains["@bazel_latex//:latex_toolchain_type"].latexinfo 134 | 135 | latex_tool = getattr(toolchain, ctx.attr._engine) 136 | dep_tools = [ 137 | toolchain.biber.files, 138 | toolchain.bibtex.files, 139 | toolchain.gsftopk.files, 140 | toolchain.kpsewhich.files, 141 | toolchain.mktexlsr.files, 142 | toolchain.kpsestat.files, 143 | toolchain.kpseaccess.files, 144 | ] 145 | 146 | bib_tool = { 147 | "biber": toolchain.biber.files.to_list()[0], 148 | "bibtex": toolchain.bibtex.files.to_list()[0], 149 | }[ctx.attr.bib_tool] 150 | 151 | engine_cmds_gen = get_engine_cmds_gen(ctx.attr._progname) 152 | engine_cmds = engine_cmds_gen(ctx, bib_tool, latex_tool) 153 | 154 | files = ( 155 | ctx.files.srcs + 156 | ctx.files.main + 157 | ctx.files.ini_files + 158 | ctx.files.font_maps + 159 | ctx.files.web2c 160 | ) 161 | 162 | env = get_env(ctx, toolchain, files) 163 | for engine_cmd in engine_cmds: 164 | ctx.actions.run( 165 | mnemonic = "LuaLatex", 166 | executable = engine_cmd["tool"], 167 | arguments = engine_cmd["cmd"], 168 | inputs = depset( 169 | direct = files + 170 | ctx.files._latexrun + 171 | engine_cmd["in"], 172 | transitive = [latex_tool.files] + dep_tools, 173 | ), 174 | outputs = engine_cmd["out"], 175 | tools = [latex_tool.files.to_list()[0]], 176 | env = env, 177 | ) 178 | 179 | latex_info = LatexOutputInfo( 180 | deps = depset(direct = files), 181 | file = ctx.outputs.out, 182 | format = ctx.attr.format, 183 | ) 184 | return [latex_info] 185 | 186 | _latex = rule( 187 | attrs = { 188 | "bib_tool": attr.string( 189 | default = "biber", 190 | values = ["biber", "bibtex"], 191 | ), 192 | "cmd_flags": attr.string_list( 193 | allow_empty = True, 194 | default = [], 195 | ), 196 | "font_maps": attr.label_list( 197 | allow_files = True, 198 | default = [ 199 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__dvips__updmap", 200 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__pdftex__updmap", 201 | ], 202 | ), 203 | "format": attr.string( 204 | doc = "Output file format", 205 | default = "pdf", 206 | values = ["dvi", "pdf"], 207 | ), 208 | "ini_files": attr.label( 209 | allow_files = True, 210 | default = "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__tex-ini-files", 211 | ), 212 | "main": attr.label( 213 | allow_single_file = [".tex"], 214 | mandatory = True, 215 | ), 216 | "srcs": attr.label_list(allow_files = True), 217 | "web2c": attr.label( 218 | allow_files = True, 219 | default = "@bazel_latex_texlive//:texlive_texmf__texmf-dist__web2c", 220 | ), 221 | "_dvi_sub": attr.label( 222 | default = "@bazel_latex//:dvi_sub", 223 | executable = True, 224 | cfg = "exec", 225 | ), 226 | # TODO: Suggestion to make _engine public so that the 227 | # user can set their engine of choice 228 | "_engine": attr.string(default = "luahbtex"), 229 | "_latexrun": attr.label( 230 | default = "@bazel_latex_latexrun//:latexrun", 231 | executable = True, 232 | cfg = "exec", 233 | ), 234 | "_progname": attr.string(default = "lualatex"), 235 | }, 236 | outputs = {"out": "%{name}.%{format}"}, 237 | toolchains = ["@bazel_latex//:latex_toolchain_type"], 238 | implementation = _latex_impl, 239 | ) 240 | 241 | def dvisvgm_pdf_specfic_input(ctx, flags, env): 242 | """ 243 | Handle dvisvgm specific flags for pdf input 244 | 245 | Args: 246 | ctx: For accessing the inputs parameters. 247 | flags: dvisvgm arguments to extend with pdf specific flags 248 | env: Environment variable dict to extend with pdf specific values 249 | """ 250 | flags.append("--pdf") 251 | env.update(ctx.attr.ghostscript_envs) 252 | libgs_path = "" 253 | for libgs_file in ctx.files.libgs: 254 | if libgs_file.basename.startswith("libgs.{}".format(ctx.attr.libgs_ext)): 255 | libgs_path = libgs_file.path 256 | if libgs_path == "": 257 | fail("libgs not found, required when input format is pdf") 258 | 259 | # realpath does not exist on mac OS X prior to mac OS 13 260 | if ctx.attr.libgs_ext == "dylib": 261 | flags.append("--libgs=$(/usr/local/bin/python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' {})".format(libgs_path)) 262 | else: 263 | flags.append("--libgs={}".format(libgs_path)) 264 | 265 | def _latex_to_svg_impl(ctx): 266 | toolchain = ctx.toolchains["@bazel_latex//:latex_toolchain_type"].latexinfo 267 | 268 | src = ctx.attr.src 269 | if LatexOutputInfo in src: 270 | input_file = src[LatexOutputInfo].file 271 | input_format = src[LatexOutputInfo].format 272 | files = [src[LatexOutputInfo].deps] 273 | else: 274 | input_file = ctx.file.src 275 | input_format = input_file.extension 276 | files = [] 277 | 278 | tree = ctx.actions.declare_directory(ctx.label.name) 279 | flags = [] 280 | flags.append("--output={}/{}-%p.svg".format(tree.path, ctx.label.name)) 281 | flags.extend(ctx.attr.args) 282 | env = get_env(ctx, toolchain, files[0].to_list() + ctx.files.deps) 283 | if "pdf" in input_format: 284 | dvisvgm_pdf_specfic_input(ctx, flags, env) 285 | elif "eps" in input_format: 286 | flags.append("--eps") 287 | 288 | string_list = [] 289 | for fm in ctx.attr.font_maps: 290 | for fm_file in fm.files.to_list(): 291 | string_list.append(fm_file.path) 292 | 293 | flags.append("--fontmap={}".format(",".join(string_list))) 294 | 295 | all_dep_files = [] 296 | for dep in files: 297 | all_dep_files.extend(dep.to_list()) 298 | 299 | arguments = [ 300 | toolchain.dvisvgm.files.to_list()[0].path, 301 | ] + flags + [ 302 | ctx.files.src[0].path, 303 | ] 304 | 305 | ctx.actions.run_shell( 306 | mnemonic = "DviSvgM", 307 | command = " ".join(arguments), 308 | inputs = depset( 309 | direct = files[0].to_list() + ctx.files.src + 310 | toolchain.kpsewhich.files.to_list() + 311 | toolchain.dvisvgm.files.to_list() + 312 | ctx.files.libgs + 313 | ctx.files.deps + 314 | all_dep_files, 315 | ), 316 | outputs = [tree], 317 | env = env, 318 | ) 319 | 320 | return [DefaultInfo(files = depset([tree]))] 321 | 322 | _latex_to_svg = rule( 323 | attrs = { 324 | "args": attr.string_list( 325 | ), 326 | "deps": attr.label_list(), 327 | "font_maps": attr.label_list( 328 | allow_files = True, 329 | default = [ 330 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__dvips__updmap", 331 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__pdftex__updmap", 332 | ], 333 | ), 334 | "ghostscript_envs": attr.string_dict( 335 | allow_empty = True, 336 | default = {"GS_OPTIONS": "-dNEWPDF=false"}, 337 | ), 338 | "libgs": attr.label( 339 | allow_files = True, 340 | doc = """File or target of ghostscript shared library.""", 341 | ), 342 | "libgs_ext": attr.string(), 343 | "src": attr.label(allow_single_file = [".dvi", ".pdf", ".eps"]), 344 | "web2c": attr.label( 345 | allow_files = True, 346 | default = "@bazel_latex_texlive//:texlive_texmf__texmf-dist__web2c", 347 | ), 348 | }, 349 | toolchains = ["@bazel_latex//:latex_toolchain_type"], 350 | implementation = _latex_to_svg_impl, 351 | ) 352 | 353 | def latex_document( 354 | name, 355 | main, 356 | srcs = [], 357 | tags = [], 358 | cmd_flags = [], 359 | format = "pdf", 360 | bib_tool = "biber", 361 | **kwargs): 362 | _latex( 363 | name = name, 364 | # TODO: Add a deps field, for adding external deps such 365 | # as core_deps 366 | srcs = srcs + ["@bazel_latex//:core_dependencies"], 367 | main = main, 368 | tags = tags, 369 | cmd_flags = cmd_flags, 370 | format = format, 371 | bib_tool = bib_tool, 372 | **kwargs 373 | ) 374 | 375 | # Convenience rule for viewing outputs. 376 | native.sh_binary( 377 | name = "{}_view_output".format(name), 378 | srcs = ["@bazel_latex//:view_output.sh"], 379 | data = [":{}.{}".format(name, format)], 380 | args = ["$(location :{}.{})".format(name, format)], 381 | tags = tags, 382 | ) 383 | 384 | # Convenience rule for viewing outputs, silencing stderr. 385 | native.sh_binary( 386 | name = "{}_view".format(name), 387 | srcs = ["@bazel_latex//:view_output.sh"], 388 | data = [":{}.{}".format(name, format)], 389 | args = [ 390 | "$(location :{}.{})".format(name, format), 391 | "None", 392 | ], 393 | tags = tags, 394 | ) 395 | 396 | def latex_to_svg( 397 | name, 398 | src, 399 | args = [], 400 | deps = [], 401 | ghostscript_envs = {"GS_OPTIONS": "-dNEWPDF=false"}, 402 | libgs = None, 403 | **kwargs): 404 | _latex_to_svg( 405 | name = "{}_svg".format(name), 406 | src = src, 407 | args = args, 408 | deps = deps + [ 409 | "@bazel_latex//:core_dependencies", 410 | "@bazel_latex//:ghostscript_dependencies", 411 | ], 412 | ghostscript_envs = ghostscript_envs, 413 | libgs = libgs, 414 | libgs_ext = select({ 415 | "@platforms//os:osx": "dylib", 416 | "@platforms//os:windows": "dll", 417 | "//conditions:default": "so", 418 | }), 419 | **kwargs 420 | ) 421 | 422 | native.filegroup( 423 | name = name, 424 | srcs = [":{}_svg".format(name)], 425 | **kwargs 426 | ) 427 | -------------------------------------------------------------------------------- /latex_engine_cmds.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | This module contains the specializations of commands 3 | depending on tool or engine. 4 | """ 5 | 6 | def add_flags(ctx, fmt, output_path, bib_tool): 7 | """ 8 | Set flags for supplying arguments to latexrun and the engine. 9 | 10 | Args: 11 | ctx: For accessing the flags 12 | fmt: Format file 13 | output_path: path of the output artifact 14 | bib_tool: bib tool of choice 15 | 16 | Returns: 17 | Flags for the latexrun command 18 | """ 19 | cmd = [ 20 | "--latex-args=--progname={}".format(ctx.attr._progname), 21 | "--output-format={}".format(ctx.attr.format), 22 | "--shell-escape", 23 | "--jobname={}".format(ctx.label.name), 24 | "--fmt={}".format(fmt.path), 25 | ] 26 | 27 | flags = [ 28 | " ".join(cmd), 29 | ] 30 | 31 | for value in ctx.attr.cmd_flags: 32 | if "output-format" in value and ctx.attr.format not in value: 33 | fail( 34 | "Value of attr format ({}), ".format(ctx.attr.format) + 35 | "conflicts with value of flag {}".format(value), 36 | ) 37 | flags.append(value) 38 | dir_count = len(output_path.split("/")) - 1 39 | dir_pos = dir_count * "../" 40 | flags.append("--bibtex-cmd=" + dir_pos + bib_tool.path) 41 | flags.append("--bibtex-args=" + "--input-directory=" + dir_pos) 42 | return flags 43 | 44 | def lualatex_engine_cmd_gen(ctx, bib_tool, latex_tool): 45 | """ 46 | Generate commands specific for the lualatex engine. 47 | 48 | This function generates these commands: 49 | - generate format file 50 | - call latex to build the document 51 | 52 | Args: 53 | ctx: For accessing the inputs parameters. 54 | bib_tool: bib tool of choice. 55 | latex_tool: The latex engine to use, in this case we make the 56 | assumption that it is the luahbtex binary (This should be 57 | enforced more strongly). 58 | 59 | Returns: 60 | A list of the commands 61 | """ 62 | 63 | fmt = ctx.actions.declare_file( 64 | ctx.label.name + "/" + ctx.attr._progname + ".fmt", 65 | ) 66 | ini_args = ctx.actions.args() 67 | ini_files_path = ctx.files.ini_files[0].dirname 68 | ini_args.add("-ini") 69 | ini_args.add( 70 | "--output-directory", 71 | ctx.outputs.out.dirname + "/" + ctx.label.name, 72 | ) 73 | ini_args.add("{}/{}.ini".format(ini_files_path, ctx.attr._progname)) 74 | 75 | args = ctx.actions.args() 76 | args.add( 77 | "--latex-cmd={}".format( 78 | latex_tool.files.to_list()[0].path, 79 | ), 80 | ) 81 | args.add("-Wall") 82 | 83 | if ctx.attr.format == "dvi": 84 | absolute_font_path_dvi = ctx.actions.declare_file( 85 | ctx.label.name + "/" + ctx.outputs.out.basename, 86 | ) 87 | 88 | args.add("-O=" + absolute_font_path_dvi.dirname) 89 | args.add_all(add_flags(ctx, fmt, absolute_font_path_dvi.path, bib_tool)) 90 | args.add(ctx.file.main.path) 91 | 92 | post_process_dvi_args = ctx.actions.args() 93 | post_process_dvi_args.add(absolute_font_path_dvi) 94 | post_process_dvi_args.add(ctx.outputs.out) 95 | 96 | engine_cmds = [ 97 | { 98 | "cmd": [ini_args], 99 | "in": [], 100 | "out": [fmt], 101 | "tool": latex_tool.files.to_list()[0], 102 | }, 103 | { 104 | "cmd": [args], 105 | "in": [fmt], 106 | "out": [absolute_font_path_dvi], 107 | "tool": ctx.executable._latexrun, 108 | }, 109 | { 110 | "cmd": [post_process_dvi_args], 111 | "in": [absolute_font_path_dvi], 112 | "out": [ctx.outputs.out], 113 | "tool": ctx.executable._dvi_sub, 114 | }, 115 | ] 116 | else: 117 | args.add("-O=" + ctx.outputs.out.dirname) 118 | args.add_all(add_flags(ctx, fmt, ctx.outputs.out.path, bib_tool)) 119 | args.add(ctx.file.main.path) 120 | 121 | engine_cmds = [ 122 | { 123 | "cmd": [ini_args], 124 | "in": [], 125 | "out": [fmt], 126 | "tool": latex_tool.files.to_list()[0], 127 | }, 128 | { 129 | "cmd": [args], 130 | "in": [fmt], 131 | "out": [ctx.outputs.out], 132 | "tool": ctx.executable._latexrun, 133 | }, 134 | ] 135 | 136 | return engine_cmds 137 | -------------------------------------------------------------------------------- /packages/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load(":packages.bzl", "latex_package") 2 | 3 | # Externally usable library targets. 4 | 5 | latex_package( 6 | name = "adjustbox", 7 | srcs = [ 8 | ":collectbox", 9 | ":epstopdf-base", 10 | ":graphicx", 11 | ":pgf", 12 | ":xkeyval", 13 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__adjustbox", 14 | ], 15 | tests = ["adjustbox_test.tex"], 16 | ) 17 | 18 | latex_package( 19 | name = "algorithm2e", 20 | srcs = [ 21 | ":float", 22 | ":ifoddpage", 23 | ":ifthen", 24 | ":relsize", 25 | ":xspace", 26 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__algorithm2e", 27 | ], 28 | tests = ["algorithm2e_test.tex"], 29 | ) 30 | 31 | latex_package( 32 | name = "amsgen", 33 | srcs = [":amsmath"], 34 | tests = ["amsgen_test.tex"], 35 | ) 36 | 37 | latex_package( 38 | name = "amsmath", 39 | srcs = [ 40 | ":amsfonts", 41 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__amsmath", 42 | ], 43 | tests = ["amsmath_test.tex"], 44 | ) 45 | 46 | latex_package( 47 | name = "amstext", 48 | srcs = [":amsmath"], 49 | tests = ["amstext_test.tex"], 50 | ) 51 | 52 | latex_package( 53 | name = "amssymb", 54 | srcs = [ 55 | ":amsfonts", 56 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__amsfonts__symbols", 57 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__amsfonts__symbols", 58 | ], 59 | tests = ["amssymb_test.tex"], 60 | ) 61 | 62 | latex_package( 63 | name = "amsthm", 64 | srcs = [":amscls"], 65 | tests = ["amsthm_test.tex"], 66 | ) 67 | 68 | latex_package( 69 | name = "array", 70 | srcs = [":tools"], 71 | tests = ["array_test.tex"], 72 | ) 73 | 74 | latex_package( 75 | name = "auxhook", 76 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__auxhook"], 77 | tests = ["auxhook_test.tex"], 78 | ) 79 | 80 | latex_package( 81 | name = "babel_dutch", 82 | srcs = [ 83 | ":babel", 84 | ":hyph_utf8", 85 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__babel-dutch", 86 | ], 87 | tests = ["babel_dutch_test.tex"], 88 | ) 89 | 90 | latex_package( 91 | name = "babel_english", 92 | srcs = [ 93 | ":babel", 94 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__babel-english", 95 | ], 96 | tests = ["babel_english_test.tex"], 97 | ) 98 | 99 | latex_package( 100 | name = "beamer", 101 | srcs = [ 102 | ":amsmath", 103 | ":amssymb", 104 | ":amsthm", 105 | ":enumerate", 106 | ":etoolbox", 107 | ":geometry", 108 | ":hyperref", 109 | ":ifpdf", 110 | ":pgfcore", 111 | ":translator", 112 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__beamer", 113 | ], 114 | tests = [ 115 | "beamer_themedefault_test.tex", 116 | "beamer_themesplit_test.tex", 117 | ], 118 | ) 119 | 120 | latex_package( 121 | name = "beamertheme-metropolis", 122 | srcs = [ 123 | ":beamer", 124 | ":fontspec", 125 | ":grfext", 126 | ":pgfopts", 127 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__beamertheme-metropolis", 128 | ], 129 | tests = [ 130 | "beamertheme-metropolis_test.tex", 131 | ], 132 | ) 133 | 134 | # Package is tested in example PDF 135 | latex_package( 136 | name = "biblatex", 137 | srcs = [ 138 | ":iftex", 139 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__oberdiek", 140 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__biblatex", 141 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__etoolbox", 142 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__graphics", 143 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__hyperref", 144 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__logreq", 145 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__oberdiek", 146 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__url", 147 | ], 148 | ) 149 | 150 | latex_package( 151 | name = "booktabs", 152 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__booktabs"], 153 | tests = ["booktabs_test.tex"], 154 | ) 155 | 156 | latex_package( 157 | name = "calc", 158 | srcs = [":tools"], 159 | tests = ["calc_test.tex"], 160 | ) 161 | 162 | latex_package( 163 | name = "capt-of", 164 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__capt-of"], 165 | tests = ["capt-of_test.tex"], 166 | ) 167 | 168 | latex_package( 169 | name = "caption", 170 | srcs = [ 171 | ":keyval", 172 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__caption", 173 | ], 174 | tests = ["caption_test.tex"], 175 | ) 176 | 177 | latex_package( 178 | name = "changepage", 179 | srcs = [ 180 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__changepage", 181 | ], 182 | tests = ["changepage_test.tex"], 183 | ) 184 | 185 | latex_package( 186 | name = "cleveref", 187 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__cleveref"], 188 | tests = ["cleveref_test.tex"], 189 | ) 190 | 191 | latex_package( 192 | name = "collectbox", 193 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__collectbox"], 194 | tests = ["collectbox_test.tex"], 195 | ) 196 | 197 | latex_package( 198 | name = "color", 199 | srcs = [":graphics_oberdiek"], 200 | tests = ["color_test.tex"], 201 | ) 202 | 203 | latex_package( 204 | name = "colortbl", 205 | srcs = [ 206 | ":array", 207 | ":color", 208 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__colortbl", 209 | ], 210 | tests = ["colortbl_test.tex"], 211 | ) 212 | 213 | latex_package( 214 | name = "contour", 215 | srcs = [ 216 | ":color", 217 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__contour", 218 | ], 219 | tests = ["contour_test.tex"], 220 | ) 221 | 222 | latex_package( 223 | name = "cooking-units", 224 | srcs = [ 225 | ":expl3", 226 | ":fmtcount", 227 | ":l3keys2e", 228 | ":translations", 229 | ":xfrac", 230 | ":xparse", 231 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__cooking-units", 232 | ], 233 | tests = ["cooking-units_test.tex"], 234 | ) 235 | 236 | latex_package( 237 | name = "csquotes", 238 | srcs = [ 239 | ":etoolbox", 240 | ":keyval", 241 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__csquotes", 242 | ], 243 | tests = ["csquotes_test.tex"], 244 | ) 245 | 246 | latex_package( 247 | name = "currfile", 248 | srcs = [ 249 | ":filehook", 250 | ":kvoptions", 251 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__currfile", 252 | ], 253 | tests = ["currfile_test.tex"], 254 | ) 255 | 256 | latex_package( 257 | name = "datatool", 258 | srcs = [ 259 | ":amsmath", 260 | ":etoolbox", 261 | ":fp", 262 | ":pgf", 263 | ":substr", 264 | ":xfor", 265 | ":xkeyval", 266 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__datatool", 267 | ], 268 | tests = [ 269 | "datatool_fp_test.tex", 270 | "datatool_pgfmath_test.tex", 271 | ], 272 | ) 273 | 274 | latex_package( 275 | name = "datenumber", 276 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__datenumber"], 277 | tests = ["datenumber_test.tex"], 278 | ) 279 | 280 | latex_package( 281 | name = "datetime", 282 | srcs = [ 283 | ":etoolbox", 284 | ":fmtcount", 285 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__datetime", 286 | ], 287 | tests = ["datetime_test.tex"], 288 | ) 289 | 290 | latex_package( 291 | name = "datetime2", 292 | srcs = [ 293 | ":tracklang", 294 | ":xkeyval", 295 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__datetime2", 296 | ], 297 | tests = ["datetime2_test.tex"], 298 | ) 299 | 300 | latex_package( 301 | name = "datetime2_english", 302 | srcs = [ 303 | ":datetime2", 304 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__datetime2-english", 305 | ], 306 | tests = ["datetime2_english_test.tex"], 307 | ) 308 | 309 | latex_package( 310 | name = "drawstack", 311 | srcs = [ 312 | ":tikz", 313 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__drawstack", 314 | ], 315 | tests = ["drawstack_test.tex"], 316 | ) 317 | 318 | latex_package( 319 | name = "enumerate", 320 | srcs = [":tools"], 321 | tests = ["enumerate_test.tex"], 322 | ) 323 | 324 | latex_package( 325 | name = "enumitem", 326 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__enumitem"], 327 | tests = ["enumitem_test.tex"], 328 | ) 329 | 330 | latex_package( 331 | name = "environ", 332 | srcs = [ 333 | ":trimspaces", 334 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__environ", 335 | ], 336 | tests = ["environ_test.tex"], 337 | ) 338 | 339 | latex_package( 340 | name = "epstopdf-base", 341 | srcs = [":graphics_oberdiek"], 342 | tests = ["epstopdf-base_test.tex"], 343 | ) 344 | 345 | latex_package( 346 | name = "etoolbox", 347 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__etoolbox"], 348 | tests = ["etoolbox_test.tex"], 349 | ) 350 | 351 | latex_package( 352 | name = "eufrak", 353 | srcs = [ 354 | ":amsfonts", 355 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__amsfonts__euler", 356 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__amsfonts__euler", 357 | ], 358 | tests = ["eufrak_test.tex"], 359 | ) 360 | 361 | latex_package( 362 | name = "everyshi", 363 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__everyshi"], 364 | tests = ["everyshi_test.tex"], 365 | ) 366 | 367 | latex_package( 368 | name = "exam", 369 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__exam"], 370 | tests = ["exam_test.tex"], 371 | ) 372 | 373 | latex_package( 374 | name = "expl3", 375 | srcs = [":l3kernel"], 376 | tests = ["expl3_test.tex"], 377 | ) 378 | 379 | latex_package( 380 | name = "fancyhdr", 381 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fancyhdr"], 382 | tests = ["fancyhdr_test.tex"], 383 | ) 384 | 385 | latex_package( 386 | name = "filehook", 387 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__filehook"], 388 | tests = ["filehook_test.tex"], 389 | ) 390 | 391 | latex_package( 392 | name = "filemod", 393 | srcs = [ 394 | ":iftex", 395 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__filemod", 396 | ], 397 | tests = ["filemod_test.tex"], 398 | ) 399 | 400 | latex_package( 401 | name = "float", 402 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__float"], 403 | tests = ["float_test.tex"], 404 | ) 405 | 406 | latex_package( 407 | name = "fmtcount", 408 | srcs = [ 409 | ":amsgen", 410 | ":etoolbox", 411 | ":xkeyval", 412 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fmtcount", 413 | ], 414 | tests = ["fmtcount_test.tex"], 415 | ) 416 | 417 | latex_package( 418 | name = "fontawesome", 419 | srcs = [ 420 | ":fontspec", 421 | ":iftex", 422 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__fontawesome", 423 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fontawesome", 424 | ], 425 | tests = ["fontawesome_test.tex"], 426 | ) 427 | 428 | latex_package( 429 | name = "fontawesome5", 430 | srcs = [ 431 | ":fontspec", 432 | ":iftex", 433 | ":l3keys2e", 434 | ":luatexbase", 435 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__fontawesome5", 436 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__dvips__fontawesome5", 437 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__fontawesome5", 438 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__fontawesome5", 439 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__fontawesome5", 440 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fontawesome5", 441 | ], 442 | tests = ["fontawesome5_test.tex"], 443 | ) 444 | 445 | latex_package( 446 | name = "fontspec", 447 | srcs = [ 448 | ":xparse", 449 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fontspec", 450 | ], 451 | tests = ["fontspec_test.tex"], 452 | ) 453 | 454 | latex_package( 455 | name = "fp", 456 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__fp"], 457 | tests = ["fp_test.tex"], 458 | ) 459 | 460 | latex_package( 461 | name = "framed", 462 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__framed"], 463 | tests = ["framed_test.tex"], 464 | ) 465 | 466 | latex_package( 467 | name = "fullpage", 468 | srcs = [":preprint"], 469 | tests = ["fullpage_test.tex"], 470 | ) 471 | 472 | latex_package( 473 | name = "gensymb", 474 | srcs = [":was"], 475 | tests = ["gensymb_test.tex"], 476 | ) 477 | 478 | latex_package( 479 | name = "geometry", 480 | srcs = [ 481 | ":ifpdf", 482 | ":iftex", 483 | ":keyval", 484 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__geometry", 485 | ], 486 | tests = ["geometry_test.tex"], 487 | ) 488 | 489 | latex_package( 490 | name = "gincltex", 491 | srcs = [ 492 | ":adjustbox", 493 | ":svn-prov", 494 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__gincltex", 495 | ], 496 | tests = ["gincltex_test.tex"], 497 | ) 498 | 499 | latex_package( 500 | name = "glossaries", 501 | srcs = [ 502 | ":datatool", 503 | ":longtable", 504 | ":mfirstuc", 505 | ":textcase", 506 | ":xfor", 507 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__glossaries__base", 508 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__glossaries__styles", 509 | ], 510 | tests = ["glossaries_test.tex"], 511 | ) 512 | 513 | latex_package( 514 | name = "glossaries-extra", 515 | srcs = [ 516 | ":etoolbox", 517 | ":glossaries", 518 | ":xkeyval", 519 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__glossaries-extra", 520 | ], 521 | tests = ["glossaries-extra_test.tex"], 522 | ) 523 | 524 | latex_package( 525 | name = "gnuplottex", 526 | srcs = [ 527 | ":graphicx", 528 | ":verbatim", 529 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__catchfile", 530 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__etexcmds", 531 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__gnuplottex", 532 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__moreverb", 533 | ], 534 | tests = ["gnuplottex_test.tex"], 535 | ) 536 | 537 | latex_package( 538 | name = "graphicx", 539 | srcs = [":graphics_oberdiek"], 540 | tests = ["graphicx_test.tex"], 541 | ) 542 | 543 | latex_package( 544 | name = "grfext", 545 | srcs = [ 546 | ":kvdefinekeys", 547 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__grfext", 548 | ], 549 | tests = ["grfext_test.tex"], 550 | ) 551 | 552 | latex_package( 553 | name = "hanging", 554 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__hanging"], 555 | tests = ["hanging_test.tex"], 556 | ) 557 | 558 | latex_package( 559 | name = "helvet", 560 | srcs = [ 561 | ":psnfss", 562 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__adobe__helvetic", 563 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__urw__helvetic", 564 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__vf__adobe__helvetic", 565 | ], 566 | tests = ["helvet_test.tex"], 567 | ) 568 | 569 | latex_package( 570 | name = "hyperref", 571 | srcs = [ 572 | ":auxhook", 573 | ":iftex", 574 | ":keyval", 575 | ":ltxcmds", 576 | ":url", 577 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__bigintcalc", 578 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__bitset", 579 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__etexcmds", 580 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__gettitlestring", 581 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__intcalc", 582 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__kvdefinekeys", 583 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__pdfescape", 584 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__stringenc", 585 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__uniquecounter", 586 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__hycolor", 587 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__hyperref", 588 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__letltxmacro", 589 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__refcount", 590 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__rerunfilecheck", 591 | ], 592 | tests = ["hyperref_test.tex"], 593 | ) 594 | 595 | latex_package( 596 | name = "hyph_utf8", 597 | srcs = [ 598 | ":graphics_oberdiek", 599 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__hyph-utf8__loadhyph", 600 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__hyph-utf8__patterns__tex", 601 | ], 602 | tests = ["hyph_utf8_test.tex"], 603 | ) 604 | 605 | latex_package( 606 | name = "hyphenat", 607 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__hyphenat"], 608 | tests = ["hyphenat_test.tex"], 609 | ) 610 | 611 | latex_package( 612 | name = "ieeetran", 613 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ieeetran"], 614 | tests = ["ieeetran_test.tex"], 615 | ) 616 | 617 | latex_package( 618 | name = "ifmtarg", 619 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ifmtarg"], 620 | tests = ["ifmtarg_test.tex"], 621 | ) 622 | 623 | latex_package( 624 | name = "ifluatex", 625 | srcs = [":iftex"], 626 | tests = ["ifluatex_test.tex"], 627 | ) 628 | 629 | latex_package( 630 | name = "ifoddpage", 631 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ifoddpage"], 632 | tests = ["ifoddpage_test.tex"], 633 | ) 634 | 635 | latex_package( 636 | name = "ifpdf", 637 | srcs = [":iftex"], 638 | tests = ["ifpdf_test.tex"], 639 | ) 640 | 641 | latex_package( 642 | name = "ifthen", 643 | tests = ["ifthen_test.tex"], 644 | ) 645 | 646 | latex_package( 647 | name = "iftex", 648 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__iftex"], 649 | tests = ["iftex_test.tex"], 650 | ) 651 | 652 | # iftex used to be called ifxetex in TeXLive 2019, keeping an alias. 653 | alias( 654 | name = "ifxetex", 655 | actual = ":iftex", 656 | ) 657 | 658 | latex_package( 659 | name = "import", 660 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__import"], 661 | tests = ["import_test.tex"], 662 | ) 663 | 664 | latex_package( 665 | name = "keyval", 666 | srcs = [":graphics_oberdiek"], 667 | tests = ["keyval_test.tex"], 668 | ) 669 | 670 | latex_package( 671 | name = "koma_script", 672 | srcs = [ 673 | ":keyval", 674 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__koma-script", 675 | ], 676 | tests = ["koma_script_test.tex"], 677 | ) 678 | 679 | latex_package( 680 | name = "kvdefinekeys", 681 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__kvdefinekeys"], 682 | tests = ["kvdefinekeys_test.tex"], 683 | ) 684 | 685 | latex_package( 686 | name = "kvoptions", 687 | srcs = [":graphics_oberdiek"], 688 | tests = ["kvoptions_test.tex"], 689 | ) 690 | 691 | latex_package( 692 | name = "lastpage", 693 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lastpage"], 694 | tests = ["lastpage_test.tex"], 695 | ) 696 | 697 | latex_package( 698 | name = "lettrine", 699 | srcs = [ 700 | ":keyval", 701 | ":minifp", 702 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lettrine", 703 | ], 704 | tests = ["lettrine_test.tex"], 705 | ) 706 | 707 | latex_package( 708 | name = "lineno", 709 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lineno"], 710 | tests = ["lineno_test.tex"], 711 | ) 712 | 713 | latex_package( 714 | name = "l3keys2e", 715 | srcs = [ 716 | ":expl3", 717 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__l3keys2e", 718 | ], 719 | tests = ["l3keys2e_test.tex"], 720 | ) 721 | 722 | latex_package( 723 | name = "listings", 724 | srcs = [ 725 | ":keyval", 726 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__listings", 727 | ], 728 | tests = ["listings_test.tex"], 729 | ) 730 | 731 | latex_package( 732 | name = "lm", 733 | srcs = [ 734 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__afm__public__lm", 735 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__lm", 736 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__dvips__lm", 737 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__lm", 738 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__lm", 739 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__lm", 740 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lm", 741 | ], 742 | tests = ["lm_test.tex"], 743 | ) 744 | 745 | latex_package( 746 | name = "longtable", 747 | srcs = [":tools"], 748 | tests = ["longtable_test.tex"], 749 | ) 750 | 751 | latex_package( 752 | name = "lstautogobble", 753 | srcs = [ 754 | ":listings", 755 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__lstaddons", 756 | ], 757 | tests = ["lstautogobble_test.tex"], 758 | ) 759 | 760 | latex_package( 761 | name = "ltxcmds", 762 | srcs = [":graphics_oberdiek"], 763 | tests = ["ltxcmds_test.tex"], 764 | ) 765 | 766 | latex_package( 767 | name = "luacode", 768 | srcs = [ 769 | ":ifluatex", 770 | ":luatexbase", 771 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__lualatex__luacode", 772 | ], 773 | tests = ["luacode_test.tex"], 774 | ) 775 | 776 | latex_package( 777 | name = "luatex85", 778 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__luatex85"], 779 | tests = ["luatex85_test.tex"], 780 | ) 781 | 782 | latex_package( 783 | name = "makecell", 784 | srcs = [ 785 | ":array", 786 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__makecell", 787 | ], 788 | tests = ["makecell_test.tex"], 789 | ) 790 | 791 | latex_package( 792 | name = "marginfix", 793 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__marginfix"], 794 | tests = ["marginfix_test.tex"], 795 | ) 796 | 797 | latex_package( 798 | name = "marginnote", 799 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__marginnote"], 800 | tests = ["marginnote_test.tex"], 801 | ) 802 | 803 | latex_package( 804 | name = "marvosym", 805 | srcs = [ 806 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__marvosym", 807 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__marvosym", 808 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__marvosym", 809 | ], 810 | tests = ["marvosym_test.tex"], 811 | ) 812 | 813 | latex_package( 814 | name = "mathastext", 815 | srcs = [ 816 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__mathastext", 817 | ], 818 | tests = ["mathastext_test.tex"], 819 | ) 820 | 821 | latex_package( 822 | name = "mdframed", 823 | srcs = [ 824 | ":etoolbox", 825 | ":ifluatex", 826 | ":luatexbase", 827 | ":needspace", 828 | ":tikz", 829 | ":xparse", 830 | ":zref-savepos", 831 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__mdframed", 832 | ], 833 | tests = ["mdframed_test.tex"], 834 | ) 835 | 836 | latex_package( 837 | name = "mfirstuc", 838 | srcs = [ 839 | ":etoolbox", 840 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__mfirstuc", 841 | ], 842 | tests = ["mfirstuc_test.tex"], 843 | ) 844 | 845 | latex_package( 846 | name = "mflogo", 847 | srcs = [ 848 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__afm__hoekwater__mflogo-font", 849 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__mflogo", 850 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__hoekwater__mflogo-font", 851 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__mflogo", 852 | ], 853 | tests = ["mflogo_test.tex"], 854 | ) 855 | 856 | latex_package( 857 | name = "microtype", 858 | srcs = [ 859 | ":etoolbox", 860 | ":keyval", 861 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__microtype", 862 | ], 863 | tests = ["microtype_test.tex"], 864 | ) 865 | 866 | latex_package( 867 | name = "minifp", 868 | srcs = [ 869 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__minifp", 870 | ], 871 | tests = ["minifp_test.tex"], 872 | ) 873 | 874 | latex_package( 875 | name = "mnsymbol", 876 | srcs = [ 877 | ":amsmath", 878 | ":eufrak", 879 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__mnsymbol", 880 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__mnsymbol", 881 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__mnsymbol", 882 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__mnsymbol", 883 | ], 884 | tests = ["mnsymbol_test.tex"], 885 | ) 886 | 887 | latex_package( 888 | name = "moderncv", 889 | srcs = [ 890 | ":etoolbox", 891 | ":fancyhdr", 892 | ":fontawesome5", 893 | ":hyperref", 894 | ":iftex", 895 | ":microtype", 896 | ":tikz", 897 | ":url", 898 | ":xcolor", 899 | ":xparse", 900 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__academicons", 901 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__arydshln", 902 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__moderncv", 903 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__multirow", 904 | ], 905 | tests = [ 906 | "moderncv_casual_test.tex", 907 | "moderncv_classic_test.tex", 908 | ], 909 | ) 910 | 911 | latex_package( 912 | name = "multicol", 913 | srcs = [":tools"], 914 | tests = ["multicol_test.tex"], 915 | ) 916 | 917 | latex_package( 918 | name = "needspace", 919 | srcs = [ 920 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__needspace", 921 | ], 922 | tests = ["needspace_test.tex"], 923 | ) 924 | 925 | latex_package( 926 | name = "nth", 927 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__nth"], 928 | tests = ["nth_test.tex"], 929 | ) 930 | 931 | latex_package( 932 | name = "parskip", 933 | srcs = [ 934 | ":etoolbox", 935 | ":kvoptions", 936 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__parskip", 937 | ], 938 | tests = ["parskip_test.tex"], 939 | ) 940 | 941 | latex_package( 942 | name = "pdfcomment", 943 | srcs = [ 944 | ":calc", 945 | ":datetime2", 946 | ":etoolbox", 947 | ":hyperref", 948 | ":luatex85", 949 | ":marginnote", 950 | ":soulpos", 951 | ":xkeyval", 952 | ":zref-savepos", 953 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pdfcomment", 954 | ], 955 | tests = ["pdfcomment_test.tex"], 956 | ) 957 | 958 | latex_package( 959 | name = "pgfcore", 960 | srcs = [ 961 | ":epstopdf-base", 962 | ":pgf", 963 | ], 964 | tests = ["pgfcore_test.tex"], 965 | ) 966 | 967 | latex_package( 968 | name = "pgfopts", 969 | srcs = [ 970 | ":pgf", 971 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgfopts", 972 | ], 973 | tests = ["pgfopts_test.tex"], 974 | ) 975 | 976 | latex_package( 977 | name = "pgfplots", 978 | srcs = [ 979 | ":pgf", 980 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__pgfplots", 981 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgfplots", 982 | ], 983 | tests = ["pgfplots_test.tex"], 984 | ) 985 | 986 | latex_package( 987 | name = "placeat", 988 | srcs = [ 989 | ":luacode", 990 | ":luatexbase", 991 | ":xparse", 992 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__scripts__placeat", 993 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__lualatex__placeat", 994 | ], 995 | tests = ["placeat_test.tex"], 996 | ) 997 | 998 | latex_package( 999 | name = "placeins", 1000 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__placeins"], 1001 | tests = ["placeins_test.tex"], 1002 | ) 1003 | 1004 | latex_package( 1005 | name = "ragged2e", 1006 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ragged2e"], 1007 | tests = ["ragged2e_test.tex"], 1008 | ) 1009 | 1010 | latex_package( 1011 | name = "relsize", 1012 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__relsize"], 1013 | tests = ["relsize_test.tex"], 1014 | ) 1015 | 1016 | latex_package( 1017 | name = "silence", 1018 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__silence"], 1019 | tests = ["silence_test.tex"], 1020 | ) 1021 | 1022 | latex_package( 1023 | name = "siunitx", 1024 | srcs = [ 1025 | ":amstext", 1026 | ":array", 1027 | ":color", 1028 | ":expl3", 1029 | ":l3keys2e", 1030 | ":xparse", 1031 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__siunitx", 1032 | ], 1033 | tests = ["siunitx_test.tex"], 1034 | ) 1035 | 1036 | latex_package( 1037 | name = "soul", 1038 | srcs = [ 1039 | ":ec", 1040 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__soul", 1041 | ], 1042 | tests = ["soul_test.tex"], 1043 | ) 1044 | 1045 | latex_package( 1046 | name = "soulutf8", 1047 | srcs = [ 1048 | ":soul", 1049 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__etexcmds", 1050 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__soulutf8", 1051 | ], 1052 | tests = ["soulutf8_test.tex"], 1053 | ) 1054 | 1055 | latex_package( 1056 | name = "soulpos", 1057 | srcs = [ 1058 | ":keyval", 1059 | ":soulutf8", 1060 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__soulpos", 1061 | ], 1062 | tests = ["soulpos_test.tex"], 1063 | ) 1064 | 1065 | latex_package( 1066 | name = "standalone", 1067 | srcs = [ 1068 | ":currfile", 1069 | ":filemod", 1070 | ":gincltex", 1071 | ":graphics_oberdiek", 1072 | ":luatex85", 1073 | ":xkeyval", 1074 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__standalone", 1075 | ], 1076 | tests = [ 1077 | "standalone_documentclass_test.tex", 1078 | "standalone_package_test.tex", 1079 | ], 1080 | ) 1081 | 1082 | latex_package( 1083 | name = "subcaption", 1084 | srcs = [":caption"], 1085 | tests = ["subcaption_test.tex"], 1086 | ) 1087 | 1088 | latex_package( 1089 | name = "substr", 1090 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__substr"], 1091 | tests = ["substr_test.tex"], 1092 | ) 1093 | 1094 | latex_package( 1095 | name = "svn-prov", 1096 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__svn-prov"], 1097 | tests = ["svn-prov_test.tex"], 1098 | ) 1099 | 1100 | latex_package( 1101 | name = "tabularx", 1102 | srcs = [":tools"], 1103 | tests = ["tabularx_test.tex"], 1104 | ) 1105 | 1106 | latex_package( 1107 | name = "tabulary", 1108 | srcs = [ 1109 | ":array", 1110 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tabulary", 1111 | ], 1112 | tests = ["tabulary_test.tex"], 1113 | ) 1114 | 1115 | latex_package( 1116 | name = "tcolorbox", 1117 | srcs = [ 1118 | ":environ", 1119 | ":etoolbox", 1120 | ":pgf", 1121 | ":verbatim", 1122 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tcolorbox", 1123 | ], 1124 | tests = ["tcolorbox_test.tex"], 1125 | ) 1126 | 1127 | latex_package( 1128 | name = "textcase", 1129 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__textcase"], 1130 | tests = ["textcase_test.tex"], 1131 | ) 1132 | 1133 | latex_package( 1134 | name = "tgheros", 1135 | srcs = [ 1136 | ":kvoptions", 1137 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__tex-gyre", 1138 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tex-gyre", 1139 | ], 1140 | tests = ["tgheros_test.tex"], 1141 | ) 1142 | 1143 | latex_package( 1144 | name = "tikz", 1145 | srcs = [":pgf"], 1146 | tests = ["tikz_test.tex"], 1147 | ) 1148 | 1149 | latex_package( 1150 | name = "tikz-qtree", 1151 | srcs = [ 1152 | ":pgf", 1153 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tikz-qtree", 1154 | ], 1155 | tests = ["tikz-qtree_test.tex"], 1156 | ) 1157 | 1158 | latex_package( 1159 | name = "titlesec", 1160 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__titlesec"], 1161 | tests = ["titlesec_test.tex"], 1162 | ) 1163 | 1164 | latex_package( 1165 | name = "titling", 1166 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__titling"], 1167 | tests = ["titling_test.tex"], 1168 | ) 1169 | 1170 | latex_package( 1171 | name = "tocloft", 1172 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tocloft"], 1173 | tests = ["tocloft_test.tex"], 1174 | ) 1175 | 1176 | latex_package( 1177 | name = "tracklang", 1178 | srcs = [ 1179 | ":etoolbox", 1180 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__tracklang", 1181 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tracklang", 1182 | ], 1183 | tests = ["tracklang_test.tex"], 1184 | ) 1185 | 1186 | latex_package( 1187 | name = "translations", 1188 | srcs = [ 1189 | ":babel", 1190 | ":etoolbox", 1191 | ":koma_script", 1192 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__translations", 1193 | ], 1194 | tests = ["translations_test.tex"], 1195 | tests_deps = [ 1196 | ":babel_dutch", 1197 | ":babel_english", 1198 | ], 1199 | ) 1200 | 1201 | latex_package( 1202 | name = "translator", 1203 | srcs = [ 1204 | ":babel", 1205 | ":keyval", 1206 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__translator", 1207 | ], 1208 | tests = ["translator_test.tex"], 1209 | ) 1210 | 1211 | latex_package( 1212 | name = "trimspaces", 1213 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__trimspaces"], 1214 | tests = ["trimspaces_test.tex"], 1215 | ) 1216 | 1217 | latex_package( 1218 | name = "ulem", 1219 | srcs = [ 1220 | ":latxfont", 1221 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__ulem", 1222 | ], 1223 | tests = ["ulem_test.tex"], 1224 | ) 1225 | 1226 | latex_package( 1227 | name = "unicode-math", 1228 | srcs = [ 1229 | ":amsmath", 1230 | ":fontspec", 1231 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__lm-math", 1232 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__etoolbox", 1233 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__filehook", 1234 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__l3keys2e", 1235 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__unicode-math", 1236 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__lualatex__lualatex-math", 1237 | ], 1238 | tests = ["unicode-math_test.tex"], 1239 | ) 1240 | 1241 | latex_package( 1242 | name = "units", 1243 | srcs = [ 1244 | ":ifthen", 1245 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__units", 1246 | ], 1247 | tests = ["units_test.tex"], 1248 | ) 1249 | 1250 | latex_package( 1251 | name = "upquote", 1252 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__upquote"], 1253 | tests = ["upquote_test.tex"], 1254 | ) 1255 | 1256 | latex_package( 1257 | name = "url", 1258 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__url"], 1259 | tests = ["url_test.tex"], 1260 | ) 1261 | 1262 | latex_package( 1263 | name = "verbatim", 1264 | srcs = [":tools"], 1265 | tests = ["verbatim_test.tex"], 1266 | ) 1267 | 1268 | latex_package( 1269 | name = "xcharter", 1270 | srcs = [ 1271 | ":cyrillic", 1272 | ":etoolbox", 1273 | ":fontspec", 1274 | ":iftex", 1275 | ":ly1", 1276 | ":psnfss", 1277 | ":times", 1278 | ":xkeyval", 1279 | ":xstring", 1280 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__afm__public__xcharter", 1281 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__enc__dvips__xcharter", 1282 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__map__dvips__xcharter", 1283 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__opentype__public__xcharter", 1284 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__xcharter", 1285 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__xcharter", 1286 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__vf__public__xcharter", 1287 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__carlisle", 1288 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xcharter", 1289 | ], 1290 | tests = ["xcharter_test.tex"], 1291 | ) 1292 | 1293 | latex_package( 1294 | name = "xcolor", 1295 | srcs = [ 1296 | ":colortbl", 1297 | ":graphics_oberdiek", 1298 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xcolor", 1299 | ], 1300 | tests = ["xcolor_test.tex"], 1301 | ) 1302 | 1303 | latex_package( 1304 | name = "xfor", 1305 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xfor"], 1306 | tests = ["xfor_test.tex"], 1307 | ) 1308 | 1309 | latex_package( 1310 | name = "xfrac", 1311 | srcs = [ 1312 | ":amstext", 1313 | ":graphicx", 1314 | ":l3keys2e", 1315 | ":xparse", 1316 | ":xtemplate", 1317 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__xfrac", 1318 | ], 1319 | tests = ["xfrac_test.tex"], 1320 | ) 1321 | 1322 | latex_package( 1323 | name = "xifthen", 1324 | srcs = [ 1325 | ":calc", 1326 | ":ifmtarg", 1327 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xifthen", 1328 | ], 1329 | tests = ["xifthen_test.tex"], 1330 | ) 1331 | 1332 | latex_package( 1333 | name = "xkeyval", 1334 | srcs = [ 1335 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__xkeyval", 1336 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__xkeyval", 1337 | ], 1338 | tests = ["xkeyval_test.tex"], 1339 | ) 1340 | 1341 | latex_package( 1342 | name = "xparse", 1343 | srcs = [ 1344 | ":expl3", 1345 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__xparse", 1346 | ], 1347 | tests = ["xparse_test.tex"], 1348 | ) 1349 | 1350 | latex_package( 1351 | name = "xspace", 1352 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tools"], 1353 | tests = ["xspace_test.tex"], 1354 | ) 1355 | 1356 | latex_package( 1357 | name = "xstring", 1358 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__xstring"], 1359 | tests = ["xstring_test.tex"], 1360 | ) 1361 | 1362 | latex_package( 1363 | name = "xtemplate", 1364 | srcs = [ 1365 | ":amstext", 1366 | ":expl3", 1367 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3packages__xtemplate", 1368 | ], 1369 | tests = ["xtemplate_test.tex"], 1370 | tests_deps = [ 1371 | ":csquotes", 1372 | ":fontspec", 1373 | ":xcolor", 1374 | ":xparse", 1375 | ":xspace", 1376 | ], 1377 | ) 1378 | 1379 | latex_package( 1380 | name = "zref-savepos", 1381 | srcs = [ 1382 | ":auxhook", 1383 | ":iftex", 1384 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__etexcmds", 1385 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__kvdefinekeys", 1386 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__zref", 1387 | ], 1388 | tests = ["zref-savepos_test.tex"], 1389 | ) 1390 | 1391 | # Internal library targets. 1392 | 1393 | filegroup( 1394 | name = "amscls", 1395 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__amscls"], 1396 | ) 1397 | 1398 | filegroup( 1399 | name = "amsfonts", 1400 | srcs = [ 1401 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__public__amsfonts__cmextra", 1402 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__amsfonts", 1403 | ], 1404 | ) 1405 | 1406 | filegroup( 1407 | name = "babel", 1408 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__babel"], 1409 | ) 1410 | 1411 | filegroup( 1412 | name = "ctablestack", 1413 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__luatex__ctablestack"], 1414 | ) 1415 | 1416 | filegroup( 1417 | name = "cyrillic", 1418 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__cyrillic"], 1419 | ) 1420 | 1421 | filegroup( 1422 | name = "ec", 1423 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__jknappen__ec"], 1424 | ) 1425 | 1426 | # These packages have a cyclic dependency on each other. 1427 | filegroup( 1428 | name = "graphics_oberdiek", 1429 | srcs = [ 1430 | ":soul", 1431 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__oberdiek", 1432 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__epstopdf-pkg", 1433 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__graphics", 1434 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__graphics-cfg", 1435 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__graphics-def", 1436 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__oberdiek", 1437 | ], 1438 | ) 1439 | 1440 | filegroup( 1441 | name = "l3kernel", 1442 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__l3kernel"], 1443 | ) 1444 | 1445 | filegroup( 1446 | name = "latxfont", 1447 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__type1__public__amsfonts__latxfont"], 1448 | ) 1449 | 1450 | filegroup( 1451 | name = "luatexbase", 1452 | srcs = [ 1453 | ":ctablestack", 1454 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__luatex__luatexbase", 1455 | ], 1456 | ) 1457 | 1458 | filegroup( 1459 | name = "ly1", 1460 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ly1"], 1461 | ) 1462 | 1463 | filegroup( 1464 | name = "ms", 1465 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__ms"], 1466 | ) 1467 | 1468 | filegroup( 1469 | name = "pgf", 1470 | srcs = [ 1471 | ":everyshi", 1472 | ":graphicx", 1473 | ":xcolor", 1474 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__generic__pgf", 1475 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__basiclayer", 1476 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__compatibility", 1477 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__frontendlayer", 1478 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__math", 1479 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__systemlayer", 1480 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__pgf__utilities", 1481 | ], 1482 | ) 1483 | 1484 | filegroup( 1485 | name = "preprint", 1486 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__preprint"], 1487 | ) 1488 | 1489 | filegroup( 1490 | name = "psnfss", 1491 | srcs = [ 1492 | ":keyval", 1493 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__psnfss", 1494 | ], 1495 | ) 1496 | 1497 | filegroup( 1498 | name = "times", 1499 | srcs = [ 1500 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__tfm__adobe__times", 1501 | "@bazel_latex_texlive//:texlive_texmf__texmf-dist__fonts__vf__adobe__times", 1502 | ], 1503 | ) 1504 | 1505 | filegroup( 1506 | name = "tools", 1507 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__tools"], 1508 | ) 1509 | 1510 | filegroup( 1511 | name = "was", 1512 | srcs = ["@bazel_latex_texlive//:texlive_texmf__texmf-dist__tex__latex__was"], 1513 | ) 1514 | -------------------------------------------------------------------------------- /packages/adjustbox_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{adjustbox} 3 | \begin{document} 4 | \adjustbox{padding=1ex 2ex 3ex 4ex,frame,margin=1ex 2ex 3ex 4ex}{Hello, world!} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/algorithm2e_test.tex: -------------------------------------------------------------------------------- 1 | % Example from https://www.overleaf.com/learn/latex/Algorithms#The_algorithm2e_package 2 | \documentclass{article} 3 | \usepackage{algorithm2e} 4 | \RestyleAlgo{ruled} 5 | \begin{document} 6 | \begin{algorithm} 7 | $i\gets 10$\; 8 | \eIf{$i\geq 5$} 9 | { 10 | $i\gets i-1$\; 11 | }{ 12 | \If{$i\leq 3$} 13 | { 14 | $i\gets i+2$\; 15 | } 16 | } 17 | \end{algorithm} 18 | 19 | \end{document} -------------------------------------------------------------------------------- /packages/amsgen_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{amsgen} 3 | \begin{document} 4 | Hello\@addpunct 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/amsmath_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{amsmath} 3 | \begin{document} 4 | \begin{equation} 5 | \begin{split} 6 | A & = \frac{\pi r^2}{2} \\ 7 | & = \frac{1}{2} \pi r^2 8 | \end{split} 9 | \end{equation} 10 | \end{document} 11 | -------------------------------------------------------------------------------- /packages/amssymb_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{amssymb} 3 | \begin{document} 4 | $\boxdot$ 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/amstext_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{amstext} 3 | \begin{document} 4 | \[ 5 | x^{2\,\times\,\text{size of $y$}} 6 | \leq 7 | z_{i_{\text{upper bound of the array}}} 8 | \] 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/amsthm_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{amsthm} 3 | \begin{document} 4 | \begin{proof} 5 | Here is my proof 6 | \end{proof} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/array_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{array} 3 | \begin{document} 4 | \newcolumntype{C}{>{$}c<{$}} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/auxhook_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{auxhook} 3 | \begin{document} 4 | This is an example. 5 | \AddLineBeginMainAux{} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/babel_dutch_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[dutch]{babel} 3 | \begin{document} 4 | \tableofcontents 5 | \chapter{Een hoofdstuk} 6 | \section{Een gedeelte} 7 | Wat tekst. 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/babel_english_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[english]{babel} 3 | \begin{document} 4 | \tableofcontents 5 | \chapter{Some chapter} 6 | \section{Some section} 7 | Some text. 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/beamer_themedefault_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | \usepackage{beamerthemedefault} 3 | \title{Demo presentation} 4 | \author{Ed Schouten} 5 | \date{October 4, 2018} 6 | \begin{document} 7 | \maketitle 8 | \begin{frame} 9 | \frametitle{First Slide} 10 | Contents of the first slide 11 | \end{frame} 12 | \begin{frame} 13 | \frametitle{Second Slide} 14 | Contents of the second slide 15 | \end{frame} 16 | \end{document} 17 | -------------------------------------------------------------------------------- /packages/beamer_themesplit_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | \usepackage{beamerthemesplit} 3 | \title{Demo presentation} 4 | \author{Ed Schouten} 5 | \date{October 4, 2018} 6 | \begin{document} 7 | \maketitle 8 | \begin{frame} 9 | \frametitle{First Slide} 10 | Contents of the first slide 11 | \end{frame} 12 | \begin{frame} 13 | \frametitle{Second Slide} 14 | Contents of the second slide 15 | \end{frame} 16 | \end{document} 17 | -------------------------------------------------------------------------------- /packages/beamertheme-metropolis_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | \usetheme{metropolis} 3 | \title{Metropolis} 4 | \author{Foo Bar} 5 | \date{October 23, 2022} 6 | 7 | \begin{document} 8 | \maketitle 9 | \begin{frame} 10 | \frametitle{First Slide} 11 | Contents of the first slide 12 | \end{frame} 13 | \begin{frame} 14 | \frametitle{Second Slide} 15 | Contents of the second slide 16 | \end{frame} 17 | \end{document} 18 | -------------------------------------------------------------------------------- /packages/booktabs_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{booktabs} 3 | \begin{document} 4 | \begin{tabular}{@{}llr@{}} \toprule 5 | \multicolumn{2}{c}{Item} \\ \cmidrule(r){1-2} 6 | Animal & Description & Price (\$) \\ \midrule 7 | Gnat & per gram & 13.65 \\ 8 | & each & 0.01 \\ 9 | Gnu & stuffed & 92.50 \\ 10 | Emu & stuffed & 33.33 \\ 11 | Armadillo & frozen & 8.99 \\ \bottomrule 12 | \end{tabular} 13 | \end{document} 14 | -------------------------------------------------------------------------------- /packages/calc_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{calc} 3 | \begin{document} 4 | \widthof{Hallo} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/capt-of_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{capt-of} 3 | \begin{document} 4 | \captionof{figure}{Hello, world!} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/caption_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[Large]{caption} 3 | \begin{document} 4 | \begin{figure} 5 | Hello 6 | \caption{A caption with large text.} 7 | \end{figure} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/changepage_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[strict]{changepage} 3 | \begin{document} 4 | \checkoddpage 5 | \ifoddpage 6 | This is odd 7 | \else 8 | This is even 9 | \fi 10 | \end{document} 11 | -------------------------------------------------------------------------------- /packages/cleveref_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{cleveref} 3 | \begin{document} 4 | \begin{figure}[ht] 5 | \caption{First figure}\label{fig:1} 6 | \end{figure} 7 | \cref{fig:1} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/collectbox_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{collectbox} 3 | \begin{document} 4 | \collectbox{\fbox{\BOXCONTENT}}{Hello, world!} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/color_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{color} 3 | \begin{document} 4 | \pagecolor{red} 5 | \textcolor{blue}{Colors} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/colortbl_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{colortbl} 3 | \begin{document} 4 | \begin{table}[h] 5 | \centering 6 | \begin{tabular}{|c|c|c|c|c|c|c|c|} 7 | \hline 8 | \cellcolor[gray]{0.8}128&64&32&16&8&4&2&1\\\hline 9 | 1&0&1&1&0&1&0&1\\\hline 10 | \end{tabular} 11 | \end{table} 12 | \end{document} 13 | -------------------------------------------------------------------------------- /packages/contour_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{contour} 3 | \begin{document} 4 | \contour{blue}{Text with a contour.} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/cooking-units_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{cooking-units} 3 | 4 | \begin{document} 5 | \cunum{182}{C} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/csquotes_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{csquotes} 3 | \begin{document} 4 | This is a test using the "csquotes" package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/currfile_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{currfile} 3 | \begin{document} 4 | Absolute directory of the current file: \currfileabsdir 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/datatool_fp_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{datatool-fp} 3 | \begin{document} 4 | 1=2: \dtlifnumeq{1}{2}{true}{false}. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/datatool_pgfmath_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{datatool-pgfmath} 3 | \begin{document} 4 | 1=2: \dtlifnumeq{1}{2}{true}{false}. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/datenumber_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{datenumber} 3 | \begin{document} 4 | \setdate{2002}{1}{1} 5 | \thedatenumber 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/datetime2_english_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[english,useregional]{datetime2} 3 | \begin{document} 4 | This PDF was created on \DTMnow. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/datetime2_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{datetime2} 3 | \begin{document} 4 | This PDF was created on \DTMnow. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/datetime_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{datetime} 3 | \yyyymmdddate 4 | \begin{document} 5 | \today 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/drawstack_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{drawstack} 3 | 4 | \begin{document} 5 | \begin{drawstack} 6 | \cell{This is a test} 7 | \end{drawstack} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/enumerate_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{enumerate} 3 | \begin{document} 4 | \begin{enumerate}[EX i.] 5 | \item one one one one one one one 6 | one one one one\label{LA} 7 | \item two 8 | \begin{enumerate}[{example} a)] 9 | \item one of two one of two 10 | one of two\label{LB} 11 | \item two of two 12 | \end{enumerate} 13 | \item two of two 14 | \end{enumerate} 15 | \begin{enumerate}[{A}-1] 16 | \item one\label{LC} 17 | \item two 18 | \end{enumerate} 19 | \end{document} 20 | -------------------------------------------------------------------------------- /packages/enumitem_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{enumitem} 3 | \begin{document} 4 | \begin{itemize}[itemsep=1ex] 5 | \item Eggs 6 | \item Milk 7 | \end{itemize} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/environ_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{environ} 3 | \begin{document} 4 | \NewEnviron{test}{\BODY} 5 | \begin{test} 6 | Hello, world! 7 | \end{test} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/epstopdf-base_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{graphics} % Needed by epstopdf-base. 3 | \usepackage{epstopdf-base} 4 | \begin{document} 5 | TODO(edsch): Add a proper test for this package. 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/etoolbox_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{etoolbox} 3 | \newrobustcmd{\hello}[0]{Hello world!} 4 | \begin{document} 5 | \hello 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/eufrak_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{eufrak} 3 | \begin{document} 4 | $\mathfrak{A} \neq \mathcal{A}$ 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/everyshi_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{everyshi} 3 | \AtNextShipout{} 4 | \begin{document} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/exam_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{exam} 2 | 3 | \begin{document} 4 | Hello, world! 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/expl3_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{expl3} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/fancyhdr_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fancyhdr} 3 | \pagestyle{fancy} 4 | \lhead{} 5 | \chead{} 6 | \rhead{\textbf{A fancyhdr test case}} 7 | \lfoot{From: me} 8 | \cfoot{To: you} 9 | \rfoot{\thepage} 10 | \renewcommand{\headrulewidth}{0.4pt} 11 | \renewcommand{\footrulewidth}{0.4pt} 12 | \begin{document} 13 | This page uses fancyhdr. 14 | \end{document} 15 | -------------------------------------------------------------------------------- /packages/filehook_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{filehook} 3 | \AtBeginDocument{Hello} 4 | \begin{document} 5 | world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/filemod_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{filemod} 3 | \begin{document} 4 | \filemodprint{input.tex} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/float_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{float} 3 | \begin{document} 4 | \floatstyle{ruled} 5 | \newfloat{Program}{tbp}{lop}[section] 6 | Floating thing. 7 | \begin{Program} 8 | \end{Program} 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/fmtcount_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fmtcount} 3 | \begin{document} 4 | \ordinalnum{3} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/fontawesome5_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fontawesome5} 3 | \begin{document} 4 | \faGithub 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/fontawesome_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fontawesome} 3 | \begin{document} 4 | \faGithub 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/fontspec_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{fontspec} 3 | \begin{document} 4 | \begin{strongenv} 5 | Hello, world! 6 | \end{strongenv} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/fp_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fp} 3 | \begin{document} 4 | \FPeval{\result}{round(400*1.06,0)}% 5 | $400+6\%=\result$ 6 | \FPeval{\result}{round((result)*1.06,0)}% 7 | $424+6\%=\result$ 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/framed_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{framed} 3 | \begin{document} 4 | \begin{framed} 5 | copious text 6 | \end{framed} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/fullpage_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{fullpage} 3 | \begin{document} 4 | Hello, world! 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/gensymb_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{gensymb} 3 | \begin{document} 4 | $36.1 \celsius$ 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/geometry_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[top=2.54cm, bottom=3.04cm, left=2.74cm, right=2.75cm]{geometry} 3 | \begin{document} 4 | This is a document with custom geometry. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/gincltex_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{gincltex} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/glossaries-extra_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{glossaries-extra} 3 | \makeglossaries 4 | \setabbreviationstyle{long-short-sc} 5 | \setabbreviationstyle[initialism]{short-long} 6 | \glssetcategoryattribute{initialism}{insertdots}{true} 7 | \glssetcategoryattribute{initialism}{discardperiod}{true} 8 | \newabbreviation{html}{html}{hypertext markup language} 9 | \newabbreviation[category=initialism]{eg}{eg}{for example} 10 | \newabbreviation[category=initialism]{si}{SI}{sample initials} 11 | \begin{document} 12 | \tableofcontents 13 | \section{Sample} 14 | First use: \gls{eg} and \gls{si} (dots inserted) and 15 | \gls{html} (no dots). 16 | Next use: \gls{eg} and \gls{si} (dots) and \gls{html} (no dots). 17 | End of sentence: \gls{eg}. (Trailing period has been discarded.) 18 | End of sentence: \gls{si}. (Spacefactor has also been adjusted.) 19 | \printglossaries 20 | \end{document} 21 | -------------------------------------------------------------------------------- /packages/glossaries_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{glossaries} 3 | \makeglossaries 4 | \newglossaryentry{latex} 5 | { 6 | name=latex, 7 | description={Is a mark up language specially suited 8 | for scientific documents} 9 | } 10 | \newglossaryentry{maths} 11 | { 12 | name=mathematics, 13 | description={Mathematics is what mathematicians do} 14 | } 15 | \title{How to create a glossary} 16 | \author{ } 17 | \date{ } 18 | \begin{document} 19 | \maketitle 20 | The \Gls{latex} typesetting markup language is specially suitable 21 | for documents that include \gls{maths}. 22 | \clearpage 23 | \printglossaries 24 | \end{document} 25 | -------------------------------------------------------------------------------- /packages/gnuplottex_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{gnuplottex} 3 | 4 | \begin{document} 5 | \begin{figure} 6 | \centering 7 | \begin{gnuplot}[terminal=latex, terminaloptions=rotate] 8 | set key box top left 9 | set key width 4 10 | set sample 1000 11 | set xr [-5:5] 12 | set yr [-1:1] 13 | set xlabel '$x$' 14 | set ylabel '$y$' 15 | plot sin(x) w l lc 1 t '$\sin(x)$',\ 16 | cos(x) w l lc 2 t '$\cos(x)$',\ 17 | tan(x) w l lc 3 t '$\tan(x)$',\ 18 | tanh(x) w l lc 4 t '$\tanh(x)$' 19 | \end{gnuplot} 20 | \caption{This is a simple example using the pdf-terminal.} 21 | \end{figure} 22 | \end{document} 23 | -------------------------------------------------------------------------------- /packages/graphicx_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{graphicx} 3 | \begin{document} 4 | \rotatebox{45}{Hello, world!} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/grfext_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{grfext} 3 | \begin{document} 4 | This outputs to the logs. 5 | \PrintGraphicsExtensions 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/hanging_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{hanging} 3 | \begin{document} 4 | \hangpara{2em}{1} 5 | Hello 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/helvet_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{helvet} 3 | \renewcommand\familydefault{\sfdefault} 4 | \usepackage[T1]{fontenc} 5 | \begin{document} 6 | \chapter{Chapter} 7 | \section{Section} 8 | This text is using the Helvetica font. 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/hyperref_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{hyperref} 3 | \begin{document} 4 | \href{https://www.latex-project.org/}{\LaTeX} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/hyph_utf8_test.tex: -------------------------------------------------------------------------------- 1 | \RequirePackage{hyphsubst} 2 | 3 | \documentclass{article} 4 | 5 | \begin{document} 6 | Hello-there. 7 | \end{document} -------------------------------------------------------------------------------- /packages/hyphenat_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[none]{hyphenat} 3 | \begin{document} 4 | Hello, world! 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/ieeetran_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{IEEEtran} 2 | \begin{document} 3 | This is a test that should be in IEEEtran format! 4 | \end{document} 5 | -------------------------------------------------------------------------------- /packages/ifluatex_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ifluatex} 3 | \begin{document} 4 | \ifluatex 5 | luatex 6 | \else 7 | not luatex 8 | \fi 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/ifmtarg_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ifmtarg} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/ifoddpage_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{ifoddpage} 3 | \begin{document} 4 | \checkoddpage 5 | \ifoddpage 6 | Odd. 7 | \else 8 | Even. 9 | \fi 10 | \end{document} -------------------------------------------------------------------------------- /packages/ifpdf_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ifpdf} 3 | \begin{document} 4 | \ifpdf 5 | pdf 6 | \else 7 | not pdf 8 | \fi 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/iftex_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ifxetex} 3 | \begin{document} 4 | \ifxetex 5 | xetex 6 | \else 7 | not xetex 8 | \fi 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/ifthen_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ifthen} 3 | \begin{document} 4 | \ifthenelse{5 < 10}{Math is working.}{Math is broken.} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/import_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{import} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/keyval_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{keyval} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/koma_script_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{scrbase} 3 | \begin{document} 4 | TODO: Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/kvdefinekeys_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{kvdefinekeys} 3 | \begin{document} 4 | \makeatletter 5 | \kv@define@key{Foo}{Bar}{} 6 | \makeatother 7 | This doesn't output anything. 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/kvoptions_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{kvoptions} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/l3keys2e_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{l3keys2e} 3 | \ProcessKeysOptions{foo} 4 | \begin{document} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/lastpage_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{lastpage} 3 | \begin{document} 4 | \pageref{LastPage} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/lettrine_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{lettrine} 3 | \begin{document} 4 | \lettrine[lraise=0.1, nindent=0em, slope=-.5em]{T}{his} is an example. 5 | With a long enough text, the first letter should be dropped on the second 6 | line as well. 7 | The third line, on the other hand, should not be impacted at all. 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/lineno_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[left]{lineno} 3 | \begin{document} 4 | This document has line numbers. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/listings_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{listings} 3 | \begin{document} 4 | \begin{lstlisting}[language=Python] 5 | # This file intentionally left blank. 6 | \end{lstlisting} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/lm_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{lmodern} 3 | \begin{document} 4 | \scshape{This is a piece of text that uses lm.} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/longtable_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{longtable} 3 | \begin{document} 4 | \begin{longtable}{|*3{p{2cm}|}} 5 | \hline 6 | \endfirsthead 7 | {\bf First} & {\bf Second} & {\bf Third} \\ \hline 8 | Text & Other Text & Other Text 2 \\ 9 | & Other Text 3 & \\ 10 | & Other Text 4 & \\ \hline 11 | Text 5 & Other Text 6 & Other Text 7 \\ 12 | & Other Text 8 & \\ 13 | & Other Text 9 & \\ \hline 14 | \end{longtable} 15 | \end{document} 16 | -------------------------------------------------------------------------------- /packages/lstautogobble_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{lstautogobble} 3 | \usepackage{listings} 4 | \lstset{autogobble=true} 5 | \begin{document} 6 | This is a normal sentence. 7 | \begin{lstlisting}[language=Python] 8 | # This comment is not indented in the pdf. 9 | \end{lstlisting} 10 | \end{document} 11 | -------------------------------------------------------------------------------- /packages/ltxcmds_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{ltxcmds} 3 | \makeatletter 4 | \newcommand*{\getdata}[2]{% 5 | \expandafter\ltx@CarNumth\expandafter{% 6 | \the\numexpr(#1)\expandafter 7 | }#2\@nil 8 | } 9 | \makeatother 10 | \newcommand*{\mydata}{% 11 | {one} {two} {three} 12 | } 13 | \newcommand*{\mylongdata}{% 14 | {one} {two} {three} {four} {five} {six} {seven} {eight} {nine} {ten} 15 | {eleven} {twelve} {thirteen} {fourteen} {fifteen} {sixteen} 16 | {seventeen} {eighteen} {nineteen} {twenty} {twenty-one} {twenty-two} 17 | {twenty-three} {twenty-four} 18 | } 19 | \begin{document} 20 | \begin{itemize} 21 | \item \getdata{1}\mydata 22 | \item \getdata{2}\mydata 23 | \item \getdata{3}\mydata 24 | \item \getdata{24}\mylongdata 25 | \end{itemize} 26 | \end{document} 27 | -------------------------------------------------------------------------------- /packages/luacode_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{luacode} 3 | \begin{document} 4 | A random number: 5 | \begin{luacode} 6 | tex.print(1 + 1) 7 | \end{luacode} 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/luatex85_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{luatex85} 3 | \begin{document} 4 | \pdfsetrandomseed 123 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/makecell_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{makecell} 3 | \begin{document} 4 | \makecell[c]{Centered text} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/marginfix_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{marginfix} 3 | \begin{document} 4 | \marginpar{Right margin} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/marginnote_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{marginnote} 3 | \begin{document} 4 | \marginnote{This is a margin note}[3cm] 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/marvosym_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{marvosym} 3 | \begin{document} 4 | \Smiley 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/mathastext_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{mathastext} 3 | \Mathastext 4 | 5 | \begin{document} 6 | H3ll0 w0rld 7 | $H3ll0 w0rld$ 8 | \end{document} 9 | -------------------------------------------------------------------------------- /packages/mdframed_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[tikz]{mdframed} 3 | 4 | \begin{document} 5 | \begin{mdframed} 6 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 7 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 8 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 9 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 10 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 11 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 12 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 13 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 14 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 15 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 16 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 17 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 18 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 19 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 20 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 21 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 22 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 23 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 24 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 25 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 26 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 27 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 28 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 29 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 30 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 31 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 32 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 33 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 34 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 35 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 36 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 37 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 38 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 39 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 40 | This is a very very long text to trigger a page change. This is a very very long text to trigger a page change. 41 | \end{mdframed} 42 | \end{document} -------------------------------------------------------------------------------- /packages/mfirstuc_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{mfirstuc} 3 | \begin{document} 4 | \makefirstuc{hello world} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/mflogo_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{mflogo} 3 | \begin{document} 4 | This is a piece of text that uses mflogo. 5 | \MP 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/microtype_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{microtype} 3 | \begin{document} 4 | This is a piece of text that uses microtype. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/minifp_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{minifp} 3 | \begin{document} 4 | \MFPadd{1.2}{3.4}\X 5 | \X 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/mnsymbol_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{MnSymbol} 3 | \begin{document} 4 | $\odot$ 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/moderncv_casual_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt,a4paper,sans]{moderncv} 2 | \moderncvstyle{casual} 3 | \moderncvcolor{blue} 4 | \name{John}{Doe} 5 | \title{Resumé title} 6 | \address{street and number}{postcode city}{country} 7 | \phone[mobile]{+1~(234)~567~890} 8 | \phone[fixed]{+2~(345)~678~901} 9 | \phone[fax]{+3~(456)~789~012} 10 | \email{john@doe.org} 11 | \homepage{www.johndoe.com} 12 | \social[linkedin]{john.doe} 13 | \social[xing]{john\_doe} 14 | \social[twitter]{jdoe} 15 | \social[github]{jdoe} 16 | \social[gitlab]{jdoe} 17 | \social[skype]{jdoe} 18 | \extrainfo{additional information} 19 | \quote{Some quote} 20 | \begin{document} 21 | \makecvtitle 22 | \section{Education} 23 | \cventry{year--year}{Degree}{Institution}{City}{\textit{Grade}}{Description} 24 | \cventry{year--year}{Degree}{Institution}{City}{\textit{Grade}}{Description} 25 | \section{Master thesis} 26 | \cvitem{title}{\emph{Title}} 27 | \cvitem{supervisors}{Supervisors} 28 | \cvitem{description}{Short thesis abstract} 29 | \section{Experience} 30 | \subsection{Vocational} 31 | \cventry{year--year}{Job title}{Employer}{City}{}{General description no longer than 1--2 lines.\newline{} 32 | Detailed achievements: 33 | \begin{itemize} 34 | \item Achievement 1; 35 | \item Achievement 2, with sub-achievements: 36 | \begin{itemize} 37 | \item Sub-achievement (a); 38 | \item Sub-achievement (b), with sub-sub-achievements (don't do this!); 39 | \begin{itemize} 40 | \item Sub-sub-achievement i; 41 | \item Sub-sub-achievement ii; 42 | \item Sub-sub-achievement iii; 43 | \end{itemize} 44 | \item Sub-achievement (c); 45 | \end{itemize} 46 | \item Achievement 3. 47 | \end{itemize}} 48 | \cventry{year--year}{Job title}{Employer}{City}{}{Description line 1\newline{}Description line 2} 49 | \subsection{Miscellaneous} 50 | \cventry{year--year}{Job title}{Employer}{City}{}{Description} 51 | \section{Languages} 52 | \cvitemwithcomment{Language 1}{Skill level}{Comment} 53 | \cvitemwithcomment{Language 2}{Skill level}{Comment} 54 | \cvitemwithcomment{Language 3}{Skill level}{Comment} 55 | \section{Computer skills} 56 | \cvdoubleitem{category 1}{XXX, YYY, ZZZ}{category 4}{XXX, YYY, ZZZ} 57 | \cvdoubleitem{category 2}{XXX, YYY, ZZZ}{category 5}{XXX, YYY, ZZZ} 58 | \cvdoubleitem{category 3}{XXX, YYY, ZZZ}{category 6}{XXX, YYY, ZZZ} 59 | \section{Interests} 60 | \cvitem{hobby 1}{Description} 61 | \cvitem{hobby 2}{Description} 62 | \cvitem{hobby 3}{Description} 63 | \section{Extra 1} 64 | \cvlistitem{Item 1} 65 | \cvlistitem{Item 2} 66 | \cvlistitem{Item 3. This item is particularly long and therefore 67 | normally spans over several lines. Did you notice the indentation when 68 | the line wraps?} 69 | \section{Extra 2} 70 | \cvlistdoubleitem{Item 1}{Item 4} 71 | \cvlistdoubleitem{Item 2}{Item 5} 72 | \cvlistdoubleitem{Item 3}{Item 6. Like item 3 in the single column list 73 | before, this item is particularly long to wrap over several lines.} 74 | \section{References} 75 | \begin{cvcolumns} 76 | \cvcolumn{Category 1}{\begin{itemize}\item Person 1\item Person 2\item Person 3\end{itemize}} 77 | \cvcolumn{Category 2}{Amongst others:\begin{itemize}\item Person 1, and\item Person 2\end{itemize}(more upon request)} 78 | \cvcolumn[0.5]{All the rest \& some more}{\textit{That} person, and \textbf{those} also (all available upon request).} 79 | \end{cvcolumns} 80 | \clearpage 81 | \recipient{Company Recruitment team}{Company, Inc.\\123 somestreet\\some city} 82 | \date{January 01, 1984} 83 | \opening{Dear Sir or Madam,} 84 | \closing{Yours faithfully,} 85 | \enclosure[Attached]{curriculum vit\ae{}} 86 | \makelettertitle 87 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis 88 | ullamcorper neque sit amet lectus facilisis sed luctus nisl iaculis. 89 | Vivamus at neque arcu, sed tempor quam. Curabitur pharetra tincidunt 90 | tincidunt. Morbi volutpat feugiat mauris, quis tempor neque vehicula 91 | volutpat. Duis tristique justo vel massa fermentum accumsan. Mauris ante 92 | elit, feugiat vestibulum tempor eget, eleifend ac ipsum. Donec 93 | scelerisque lobortis ipsum eu vestibulum. Pellentesque vel massa at 94 | felis accumsan rhoncus. 95 | 96 | Suspendisse commodo, massa eu congue tincidunt, elit mauris pellentesque 97 | orci, cursus tempor odio nisl euismod augue. Aliquam adipiscing nibh ut 98 | odio sodales et pulvinar tortor laoreet. Mauris a accumsan ligula. Class 99 | aptent taciti sociosqu ad litora torquent per conubia nostra, per 100 | inceptos himenaeos. Suspendisse vulputate sem vehicula ipsum varius nec 101 | tempus dui dapibus. Phasellus et est urna, ut auctor erat. Sed tincidunt 102 | odio id odio aliquam mattis. Donec sapien nulla, feugiat eget adipiscing 103 | sit amet, lacinia ut dolor. Phasellus tincidunt, leo a fringilla 104 | consectetur, felis diam aliquam urna, vitae aliquet lectus orci nec 105 | velit. Vivamus dapibus varius blandit. 106 | 107 | Duis sit amet magna ante, at sodales diam. Aenean consectetur porta 108 | risus et sagittis. Ut interdum, enim varius pellentesque tincidunt, 109 | magna libero sodales tortor, ut fermentum nunc metus a ante. Vivamus 110 | odio leo, tincidunt eu luctus ut, sollicitudin sit amet metus. Nunc sed 111 | orci lectus. Ut sodales magna sed velit volutpat sit amet pulvinar diam 112 | venenatis. 113 | 114 | Albert Einstein discovered that $e=mc^2$ in 1905. 115 | \[ e=\lim_{n \to \infty} \left(1+\frac{1}{n}\right)^n \] 116 | \makeletterclosing 117 | \end{document} 118 | -------------------------------------------------------------------------------- /packages/moderncv_classic_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt,a4paper,sans]{moderncv} 2 | \moderncvstyle{classic} 3 | \moderncvcolor{blue} 4 | \name{John}{Doe} 5 | \title{Resumé title} 6 | \address{street and number}{postcode city}{country} 7 | \phone[mobile]{+1~(234)~567~890} 8 | \phone[fixed]{+2~(345)~678~901} 9 | \phone[fax]{+3~(456)~789~012} 10 | \email{john@doe.org} 11 | \homepage{www.johndoe.com} 12 | \social[linkedin]{john.doe} 13 | \social[xing]{john\_doe} 14 | \social[twitter]{jdoe} 15 | \social[github]{jdoe} 16 | \social[gitlab]{jdoe} 17 | \social[skype]{jdoe} 18 | \extrainfo{additional information} 19 | \quote{Some quote} 20 | \begin{document} 21 | \makecvtitle 22 | \section{Education} 23 | \cventry{year--year}{Degree}{Institution}{City}{\textit{Grade}}{Description} 24 | \cventry{year--year}{Degree}{Institution}{City}{\textit{Grade}}{Description} 25 | \section{Master thesis} 26 | \cvitem{title}{\emph{Title}} 27 | \cvitem{supervisors}{Supervisors} 28 | \cvitem{description}{Short thesis abstract} 29 | \section{Experience} 30 | \subsection{Vocational} 31 | \cventry{year--year}{Job title}{Employer}{City}{}{General description no longer than 1--2 lines.\newline{} 32 | Detailed achievements: 33 | \begin{itemize} 34 | \item Achievement 1; 35 | \item Achievement 2, with sub-achievements: 36 | \begin{itemize} 37 | \item Sub-achievement (a); 38 | \item Sub-achievement (b), with sub-sub-achievements (don't do this!); 39 | \begin{itemize} 40 | \item Sub-sub-achievement i; 41 | \item Sub-sub-achievement ii; 42 | \item Sub-sub-achievement iii; 43 | \end{itemize} 44 | \item Sub-achievement (c); 45 | \end{itemize} 46 | \item Achievement 3. 47 | \end{itemize}} 48 | \cventry{year--year}{Job title}{Employer}{City}{}{Description line 1\newline{}Description line 2} 49 | \subsection{Miscellaneous} 50 | \cventry{year--year}{Job title}{Employer}{City}{}{Description} 51 | \section{Languages} 52 | \cvitemwithcomment{Language 1}{Skill level}{Comment} 53 | \cvitemwithcomment{Language 2}{Skill level}{Comment} 54 | \cvitemwithcomment{Language 3}{Skill level}{Comment} 55 | \section{Computer skills} 56 | \cvdoubleitem{category 1}{XXX, YYY, ZZZ}{category 4}{XXX, YYY, ZZZ} 57 | \cvdoubleitem{category 2}{XXX, YYY, ZZZ}{category 5}{XXX, YYY, ZZZ} 58 | \cvdoubleitem{category 3}{XXX, YYY, ZZZ}{category 6}{XXX, YYY, ZZZ} 59 | \section{Interests} 60 | \cvitem{hobby 1}{Description} 61 | \cvitem{hobby 2}{Description} 62 | \cvitem{hobby 3}{Description} 63 | \section{Extra 1} 64 | \cvlistitem{Item 1} 65 | \cvlistitem{Item 2} 66 | \cvlistitem{Item 3. This item is particularly long and therefore 67 | normally spans over several lines. Did you notice the indentation when 68 | the line wraps?} 69 | \section{Extra 2} 70 | \cvlistdoubleitem{Item 1}{Item 4} 71 | \cvlistdoubleitem{Item 2}{Item 5} 72 | \cvlistdoubleitem{Item 3}{Item 6. Like item 3 in the single column list 73 | before, this item is particularly long to wrap over several lines.} 74 | \section{References} 75 | \begin{cvcolumns} 76 | \cvcolumn{Category 1}{\begin{itemize}\item Person 1\item Person 2\item Person 3\end{itemize}} 77 | \cvcolumn{Category 2}{Amongst others:\begin{itemize}\item Person 1, and\item Person 2\end{itemize}(more upon request)} 78 | \cvcolumn[0.5]{All the rest \& some more}{\textit{That} person, and \textbf{those} also (all available upon request).} 79 | \end{cvcolumns} 80 | \clearpage 81 | \recipient{Company Recruitment team}{Company, Inc.\\123 somestreet\\some city} 82 | \date{January 01, 1984} 83 | \opening{Dear Sir or Madam,} 84 | \closing{Yours faithfully,} 85 | \enclosure[Attached]{curriculum vit\ae{}} 86 | \makelettertitle 87 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis 88 | ullamcorper neque sit amet lectus facilisis sed luctus nisl iaculis. 89 | Vivamus at neque arcu, sed tempor quam. Curabitur pharetra tincidunt 90 | tincidunt. Morbi volutpat feugiat mauris, quis tempor neque vehicula 91 | volutpat. Duis tristique justo vel massa fermentum accumsan. Mauris ante 92 | elit, feugiat vestibulum tempor eget, eleifend ac ipsum. Donec 93 | scelerisque lobortis ipsum eu vestibulum. Pellentesque vel massa at 94 | felis accumsan rhoncus. 95 | 96 | Suspendisse commodo, massa eu congue tincidunt, elit mauris pellentesque 97 | orci, cursus tempor odio nisl euismod augue. Aliquam adipiscing nibh ut 98 | odio sodales et pulvinar tortor laoreet. Mauris a accumsan ligula. Class 99 | aptent taciti sociosqu ad litora torquent per conubia nostra, per 100 | inceptos himenaeos. Suspendisse vulputate sem vehicula ipsum varius nec 101 | tempus dui dapibus. Phasellus et est urna, ut auctor erat. Sed tincidunt 102 | odio id odio aliquam mattis. Donec sapien nulla, feugiat eget adipiscing 103 | sit amet, lacinia ut dolor. Phasellus tincidunt, leo a fringilla 104 | consectetur, felis diam aliquam urna, vitae aliquet lectus orci nec 105 | velit. Vivamus dapibus varius blandit. 106 | 107 | Duis sit amet magna ante, at sodales diam. Aenean consectetur porta 108 | risus et sagittis. Ut interdum, enim varius pellentesque tincidunt, 109 | magna libero sodales tortor, ut fermentum nunc metus a ante. Vivamus 110 | odio leo, tincidunt eu luctus ut, sollicitudin sit amet metus. Nunc sed 111 | orci lectus. Ut sodales magna sed velit volutpat sit amet pulvinar diam 112 | venenatis. 113 | 114 | Albert Einstein discovered that $e=mc^2$ in 1905. 115 | \[ e=\lim_{n \to \infty} \left(1+\frac{1}{n}\right)^n \] 116 | \makeletterclosing 117 | \end{document} 118 | -------------------------------------------------------------------------------- /packages/multicol_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{multicol} 3 | 4 | \begin{document} 5 | \begin{multicols}{3} 6 | \begin{itemize} 7 | \item This 8 | \item is 9 | \item a 10 | \item Test 11 | \end{itemize} 12 | \end{multicols} 13 | \end{document} 14 | -------------------------------------------------------------------------------- /packages/needspace_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{needspace} 3 | 4 | \begin{document} 5 | Some existing text 6 | \needspace{5\baselineskip} 7 | Some more text 8 | \end{document} -------------------------------------------------------------------------------- /packages/nth_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{nth} 3 | \begin{document} 4 | \nth{1} \nth{2} \nth{3} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/packages.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | Helpers for built-in packages. 3 | """ 4 | 5 | load("//:latex.bzl", "latex_document") 6 | 7 | def latex_package(name, srcs = [], tests = [], tests_deps = []): 8 | native.filegroup( 9 | name = name, 10 | srcs = srcs, 11 | visibility = ["//visibility:public"], 12 | ) 13 | 14 | for test in tests: 15 | latex_document( 16 | name = name + "_" + test, 17 | main = test, 18 | srcs = [":" + name] + tests_deps, 19 | ) 20 | -------------------------------------------------------------------------------- /packages/parskip_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{parskip} 3 | \begin{document} 4 | Paragraph one. 5 | 6 | Paragraph two. 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/pdfcomment_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{pdfcomment} 3 | \begin{document} 4 | Here we\pdfcomment[icon=Insert]{insert: miss} a word! 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/pgfcore_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{pgfcore} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/pgfopts_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{pgfopts} 3 | \begin{document} 4 | TODO: Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/pgfplots_test.tex: -------------------------------------------------------------------------------- 1 | % From https://www.overleaf.com/learn/latex/Pgfplots_package 2 | 3 | \documentclass{report} 4 | \usepackage{tikz} 5 | \usepackage{pgfplots} 6 | \begin{document} 7 | \begin{tikzpicture} 8 | \begin{axis}[ 9 | title={Temperature dependence of CuSO\(_4\cdot\)5H\(_2\)O solubility}, 10 | xlabel={Temperature [C}, 11 | ylabel={Solubility [g per 100 g water]}, 12 | xmin=0, xmax=100, 13 | ymin=0, ymax=120, 14 | xtick={0,20,40,60,80,100}, 15 | ytick={0,20,40,60,80,100,120}, 16 | legend pos=north west, 17 | ymajorgrids=true, 18 | grid style=dashed, 19 | ] 20 | 21 | \addplot[ 22 | color=blue, 23 | mark=square, 24 | ] 25 | coordinates { 26 | (0,23.1)(10,27.5)(20,32)(30,37.8)(40,44.6)(60,61.8)(80,83.8)(100,114) 27 | }; 28 | \legend{CuSO\(_4\cdot\)5H\(_2\)O} 29 | 30 | \end{axis} 31 | \end{tikzpicture} 32 | \end{document} 33 | -------------------------------------------------------------------------------- /packages/placeat_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{placeat} 3 | \begin{document} 4 | \placeat(2,5){Hello, world!} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/placeins_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{placeins} 3 | \begin{document} 4 | \FloatBarrier 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/ragged2e_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ragged2e} 3 | \begin{document} 4 | \RaggedLeft Hello there 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/relsize_test.tex: -------------------------------------------------------------------------------- 1 | % Example from: https://tex.stackexchange.com/questions/117893/why-does-relsize-1-in-normal-size-not-result-in-smaller 2 | \documentclass{article} 3 | \usepackage{relsize} 4 | \begin{document} 5 | \texttt{\small k1}: \texttt{\smaller k1} \textsmaller{\texttt{k1}} \texttt{\relsize{-1} k1} \texttt{\relsize{0} k1} \texttt{\footnotesize k1} 6 | \end{document} -------------------------------------------------------------------------------- /packages/silence_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{silence} 3 | \begin{document} 4 | \WarningFilter{foo}{bar} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/siunitx_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{siunitx} 3 | \begin{document} 4 | \si{kg.m.s^{-1}} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/soul_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{soul} 3 | \begin{document} 4 | \so{letterspacing} 5 | \caps{CAPITALS, Small Capitals} 6 | \ul{underlining} 7 | \st{overstriking} 8 | \hl{highlighting} 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/soulpos_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{soulpos} 3 | \begin{document} 4 | \ulposdef{\banana}{\rule[-.8ex]{\ulwidth}{.5pt}} 5 | \banana{Yellow} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/soulutf8_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{soulutf8} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/standalone_documentclass_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | \begin{document} 3 | This is an example. 4 | \end{document} 5 | -------------------------------------------------------------------------------- /packages/standalone_package_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage[subpreambles=true]{standalone} 3 | \begin{document} 4 | This is an example. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/subcaption_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{subcaption} 3 | \begin{document} 4 | \begin{figure} 5 | \begin{minipage}[b]{.5\linewidth} 6 | \centering\large A 7 | \subcaption{A subfigure}\label{fig:1a} 8 | \end{minipage}% 9 | \begin{minipage}[b]{.5\linewidth} 10 | \centering\large B 11 | \subcaption{Another subfigure}\label{fig:1b} 12 | \end{minipage} 13 | \caption{A figure}\label{fig:1} 14 | \end{figure} 15 | \end{document} 16 | -------------------------------------------------------------------------------- /packages/substr_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{substr} 3 | \begin{document} 4 | \IfSubStringInString{substring}{string}{true part}{false part} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/svn-prov_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{svn-prov} 3 | \ProvidesPackageSVN{$Id: svn-prov.dtx 1862 2010-04-24 14:19:07Z martin $} 4 | \begin{document} 5 | \GetFileInfoSVN* 6 | \begin{tabular}{ll} 7 | File Name & \filename \\ 8 | File Base Name & \filebase \\ 9 | File Extension & \fileext \\ 10 | File Date & \filedate \\ 11 | File Revision & \filerev \\ 12 | File Version & \fileversion \\ 13 | File Info & \fileinfo \\ 14 | \end{tabular} 15 | \end{document} 16 | -------------------------------------------------------------------------------- /packages/tabularx_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tabularx} 3 | \begin{document} 4 | \noindent\begin{tabularx}{\textwidth}{|X|X|X|} 5 | \hline 6 | Alpha & Beta & Gamma \\ \hline 7 | 0 & 2 & 4 \\ \hline 8 | 1 & 3 & 5 \\ \hline 9 | \end{tabularx} 10 | \end{document} 11 | -------------------------------------------------------------------------------- /packages/tabulary_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tabulary} 3 | \begin{document} 4 | \begin{tabulary}{1.0\textwidth}{|p{.3\textwidth}|p{.7\textwidth}|} 5 | a & b\\ 6 | \end{tabulary} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/tcolorbox_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tcolorbox} 3 | \begin{document} 4 | \begin{tcolorbox} 5 | Hello, world! 6 | \end{tcolorbox} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/textcase_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{textcase} 3 | \begin{document} 4 | \MakeTextUppercase{hello world} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/tgheros_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \begin{document} 3 | \textsf{This document uses the Heros font.} 4 | \end{document} 5 | -------------------------------------------------------------------------------- /packages/tikz-qtree_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{tikz} 3 | \usepackage{tikz-qtree} 4 | \begin{document} 5 | \Tree [.S [.NP [.Det the ] [.N cat ] ] 6 | [.VP [.V sat ] 7 | [.PP [.P on ] 8 | [.NP [.Det the ] [.N mat ] ] ] ] ] 9 | \end{document} 10 | -------------------------------------------------------------------------------- /packages/tikz_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture}[font=\LARGE] 5 | \def \tta{ -10.00000000000000 } 6 | \def \k{ -3.00000000000000 } 7 | \def \l{ 6.00000000000000 } 8 | \def \d{ 5.00000000000000 } 9 | \def \h{ 7.00000000000000 } 10 | \coordinate (A) at (0,0); 11 | \coordinate (B) at ({-\h*sin(\tta)},{\h*cos(\tta)}); 12 | \coordinate (C) at ({-\h*sin(\tta)-\d*sin(\k*\tta)}, 13 | {\h*cos(\tta)+\d*cos(\k*\tta)}); 14 | \coordinate (D) at ({-\d*sin(\k*\tta)},{\d*cos(\k*\tta)}); 15 | \coordinate (Ap) at (\l,0); 16 | \coordinate (Bp) at ({\l-\h*sin(\tta)},{\h*cos(\tta)}); 17 | \coordinate (Cp) at ({\l-\h*sin(\tta)-\d*sin(\k*\tta)}, 18 | {\h*cos(\tta)+\d*cos(\k*\tta)}); 19 | \coordinate (Dp) at ({\l-\d*sin(\k*\tta)},{\d*cos(\k*\tta)}); 20 | \fill[black] (A) circle [radius=2pt]; 21 | \fill[red] (B) circle [radius=2pt]; 22 | \fill[black] (C) circle [radius=2pt]; 23 | \fill[red] (D) circle [radius=2pt]; 24 | \fill[red] (Ap) circle [radius=2pt]; 25 | \fill[black] (Bp) circle [radius=2pt]; 26 | \fill[red] (Cp) circle [radius=2pt]; 27 | \fill[black] (Dp) circle [radius=2pt]; 28 | \filldraw[draw=red,bottom color=red!50!black, top color=cyan!50] 29 | (B) -- (Cp) -- (D); 30 | \filldraw[draw=red,bottom color=red!50!black, top color=cyan!50] 31 | (B) -- (D) -- (Ap); 32 | \filldraw[draw=red,bottom color=red!50!black, top color=cyan!50] 33 | (B) -- (Cp) -- (Ap); 34 | \draw[red,-,very thick] (Ap) -- (D) 35 | (Ap) -- (B) 36 | (Ap) -- (Cp) 37 | (B) -- (D) 38 | (Cp) -- (D) 39 | (B) -- (Cp); 40 | \draw [-,thin] (B) -- (A) 41 | (Ap) -- (Bp) 42 | (B) -- (C) 43 | (D) -- (C) 44 | (A) -- (D) 45 | (Ap) -- (A) 46 | (Cp) -- (C) 47 | (Bp) -- (B) 48 | (Bp) -- (Cp); 49 | \draw [gray,-,thin] (Dp) -- (Cp); 50 | (Dp) -- (D); 51 | (Ap) -- (Dp); 52 | \draw (Ap) node [right] {$A$} 53 | (Bp) node [right, gray] {$F$} 54 | (Cp) node [right] {$D$} 55 | (C) node [left,gray] {$E$} 56 | (D) node [left] {$B$} 57 | (A) node [left,gray] {$G$} 58 | (B) node [above left=+5pt] {$C$} 59 | (Dp) node [right,gray] {$H$}; 60 | \fill[red] (B) circle [radius=2pt]; 61 | \fill[gray] (Dp) circle [radius=2pt]; 62 | \draw[red,-,dashed, thin] (A) -- (Dp) 63 | (A) -- (Bp) 64 | (A) -- (C) 65 | (Bp) -- (Dp) 66 | (C) -- (Dp) 67 | (Bp) -- (C); 68 | \end{tikzpicture} 69 | \end{document} 70 | -------------------------------------------------------------------------------- /packages/titlesec_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{titlesec} 3 | \begin{document} 4 | \titleformat*{\section}{\itshape} 5 | \section{Italic section} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/titling_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | 3 | \usepackage{titling} 4 | 5 | \author{John Doe} 6 | \title{Foo} 7 | 8 | \begin{document} 9 | \thetitle, by \theauthor 10 | \end{document} 11 | -------------------------------------------------------------------------------- /packages/tocloft_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tocloft} 3 | \tocloftpagestyle{plain} 4 | \begin{document} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/tracklang_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{tracklang} 3 | \begin{document} 4 | \TrackLocale{nl} 5 | Dutch? 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/translations_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | 3 | \usepackage[english,dutch]{babel} 4 | \usepackage{translations} 5 | 6 | \declaretranslation{English}{Kueche}{kitchen} 7 | \declaretranslation{Dutch}{Kueche}{keuken} 8 | 9 | \begin{document} 10 | \GetTranslation{Kueche} 11 | \SaveTranslation\kitchen{Kueche} 12 | \SaveTranslationFor\keuken{dutch}{Kueche} 13 | 14 | \selectlanguage{dutch} 15 | \GetTranslation{Kueche} \kitchen\ \GetTranslationFor{dutch}{Kueche} 16 | \keuken 17 | 18 | \IfTranslation{German}{Kueche}{true}{false} \par 19 | \IfTranslation{Dutch}{Kueche}{true}{false} 20 | \end{document} 21 | -------------------------------------------------------------------------------- /packages/translator_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{translator} 3 | \newtranslation[to = German]{figure}{Abbildung} 4 | \begin{document} 5 | \translate[to = German]{figure} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/trimspaces_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{trimspaces} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/ulem_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{ulem} 3 | \begin{document} 4 | \uline{important} 5 | \uuline{urgent} 6 | \uwave{boat} 7 | \sout{wrong} 8 | \xout{removed} 9 | \dashuline{dashing} 10 | \dotuline{dotty} 11 | \end{document} 12 | -------------------------------------------------------------------------------- /packages/unicode-math_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | 3 | \usepackage{unicode-math} 4 | 5 | \begin{document} 6 | \(\mathbf{x}\) 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/units_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{units} 3 | \begin{document} 4 | \unitfrac[1]{2}{3}{m} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/upquote_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{upquote} 3 | \begin{document} 4 | \begin{verbatim} 5 | foo = 'bar' 6 | \end{verbatim} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/url_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{url} 3 | \begin{document} 4 | \url{https://www.latex-project.org/} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/verbatim_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{verbatim} 3 | \begin{document} 4 | \begin{verbatim} 5 | Hello, world! 6 | \end{verbatim} 7 | \end{document} 8 | -------------------------------------------------------------------------------- /packages/xcharter_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{XCharter} 3 | \begin{document} 4 | This uses the Charter font. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xcolor_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{xcolor} 3 | \begin{document} 4 | \pagecolor{red} 5 | \textcolor{blue}{Colors} 6 | \end{document} 7 | -------------------------------------------------------------------------------- /packages/xfor_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{xfor} 3 | \makeatletter 4 | \newcount\select@count 5 | \newcount\select@i 6 | \newcommand\select[2]{% 7 | \select@i=\z@\select@count=\z@ 8 | \@for\@@select@item:={#2}\do{\advance\select@count by\@ne}% 9 | \ifnum#1>\select@count??\else 10 | \@for\@@select@item:={#2}\do{% 11 | \advance\select@i by\@ne 12 | \ifnum#1<1??\@endfortrue\fi 13 | \ifnum#1=\select@i\@@select@item\@endfortrue\fi 14 | }% 15 | \fi 16 | } 17 | \makeatother 18 | \begin{document} 19 | \begin{itemize} 20 | \item \verb+\select{0}{A,B,C,D,E}+ gives \select{0}{A,B,C,D,E} 21 | \item \verb+\select{1}{A,B,C,D,E}+ gives \select{1}{A,B,C,D,E} 22 | \item \verb+\select{2}{A,B,C,D,E}+ gives \select{2}{A,B,C,D,E} 23 | \item \verb+\select{5}{A,B,C,D,E}+ gives \select{5}{A,B,C,D,E} 24 | \item \verb+\select{10}{A,B,C,D,E}+ gives \select{10}{A,B,C,D,E} 25 | \item \verb+\select{0}{1,2,3,4,5}+ gives \select{0}{1,2,3,4,5} 26 | \item \verb+\select{1}{1,2,3,4,5}+ gives \select{1}{1,2,3,4,5} 27 | \item \verb+\select{2}{1,2,3,4,5}+ gives \select{2}{1,2,3,4,5} 28 | \item \verb+\select{5}{1,2,3,4,5}+ gives \select{5}{1,2,3,4,5} 29 | \item \verb+\select{10}{1,2,3,4,5}+ gives \select{10}{1,2,3,4,5} 30 | \end{itemize} 31 | \end{document} 32 | -------------------------------------------------------------------------------- /packages/xfrac_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{xfrac} 3 | \begin{document} 4 | \sfrac{1}{2} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xifthen_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{xifthen} 3 | \begin{document} 4 | \ifthenelse{\endswith{foo.}{.}}{true}{false} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xkeyval_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{xkeyval} 3 | \begin{document} 4 | TODO(edsch): Add a proper test for this package. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xparse_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{xparse} 3 | \begin{document} 4 | \IfBooleanTF{\BooleanTrue}{true}{false} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xspace_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{xspace} 3 | \begin{document} 4 | One \xspace after another \xspace. 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xstring_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{xstring} 3 | \begin{document} 4 | \IfStrEq{a1b2c3}{a1b2c3}{true}{false} 5 | \end{document} 6 | -------------------------------------------------------------------------------- /packages/xtemplate_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{expl3, xtemplate, xparse, csquotes, xcolor, fontspec, xspace} 3 | 4 | \begin{document} 5 | \ExplSyntaxOn 6 | \DeclareObjectType{inlineobj}{1} 7 | \DeclareTemplateInterface{inlineobj}{span}{1} 8 | { 9 | font-face: tokenlist, 10 | font-shape: choice {italic, slanted, normal}=normal, 11 | font-weight: choice {bold, normal}=normal, 12 | font-color: tokenlist=black, 13 | quote: choice {none, enquote}=none, 14 | } 15 | 16 | \DeclareTemplateCode{inlineobj}{span}{1} 17 | { 18 | font-face = \l_font_tl, 19 | font-shape = { 20 | italic = \cs_set_nopar:Nn \afontshape: {\itshape}, 21 | slanted = \cs_set_nopar:Nn \afontshape: {\itshape}, 22 | normal = \cs_set_nopar:Nn \afontshape: {\upshape} 23 | }, 24 | font-weight= { 25 | bold = \cs_set_nopar:Nn \afontseries: {\bfseries}, 26 | normal =\cs_set_nopar:Nn \afontseries: {\mdseries} 27 | }, 28 | font-color = \l_tmpa_tl, 29 | quote = { 30 | none = \cs_set_nopar:Npn \quotemacro:n #1 {\detokenize{#1}}, 31 | enquote = \cs_set_nopar:Npn \quotemacro:n #1 {\enquote{\detokenize{#1}}}, 32 | unknown = \cs_set_nopar:Npn \quotemacro:n #1 {\detokenize{#1}} 33 | }, 34 | } 35 | { 36 | % the implementation part 37 | \AssignTemplateKeys 38 | 39 | \group_begin: 40 | \color\l_tmpa_tl 41 | \cs:w \l_font_tl \cs_end: 42 | \afontshape: 43 | \afontseries:\selectfont 44 | \quotemacro:n{#1} 45 | \group_end: 46 | } 47 | 48 | \DeclareInstance {inlineobj}{docFunction}{span} 49 | { 50 | font-shape=italic, 51 | font-weight=bold, 52 | font-color=green!40!black, 53 | quote=enquote 54 | } 55 | 56 | \DeclareDocumentCommand\docFunction { m } { 57 | \IfInstanceExistTF {inlineobj}{docFunction} 58 | {\UseInstance{inlineobj}{docFunction}{#1}} 59 | {ERROR} 60 | } 61 | 62 | \DeclareInstance {inlineobj}{tn}{span} 63 | { 64 | font-shape=normal, 65 | font-weight=normal, 66 | font-color=red!80!black, 67 | quote=none, 68 | } 69 | 70 | \DeclareDocumentCommand\tn{ m }{% 71 | \IfInstanceExistTF {inlineobj}{tn} 72 | {\UseInstance{inlineobj}{tn}{#1}} 73 | {ERROR} 74 | } 75 | \ExplSyntaxOff 76 | 77 | The function \docFunction {get_string ( )} is used throughout to get a string in LuaTeX, where macros in text paragraphs are shown as \docFunction{\my_macro} in green. Typewrite text is obtained by using \tn{\tn}. 78 | \end{document} 79 | -------------------------------------------------------------------------------- /packages/zref-savepos_test.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | \usepackage{zref-savepos} 3 | \begin{document} 4 | \zsavepos{Foo} 5 | Hello, world! 6 | \end{document} 7 | -------------------------------------------------------------------------------- /patches/latexrun-force-colors: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -416,7 +416,24 @@ class _Terminfo: 4 | else: 5 | s = self.__ensure(cap) 6 | sys.stdout.buffer.write(s) 7 | -terminfo = _Terminfo() 8 | + 9 | +class _BatchColorTerminfo: 10 | + def has(self, *caps): 11 | + for cap in caps: 12 | + if cap not in ['bold', 'setaf', 'sgr0']: 13 | + return False 14 | + return True 15 | + 16 | + def send(self, *caps): 17 | + sys.stdout.flush() 18 | + for cap in caps: 19 | + if cap == 'bold': 20 | + sys.stdout.buffer.write(b'\x1b[1m') 21 | + elif isinstance(cap, tuple) and cap[0] == 'setaf': 22 | + sys.stdout.buffer.write(b'\x1b[%dm' % (cap[1] + 30)) 23 | + elif cap == 'sgr0': 24 | + sys.stdout.buffer.write(b'\x1b[m') 25 | +terminfo = _BatchColorTerminfo() 26 | 27 | class Progress: 28 | _enabled = None 29 | -------------------------------------------------------------------------------- /patches/latexrun-pull-21: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -85,7 +85,7 @@ def main(): 4 | action=ArgParserWarnAction, dest='nowarns', default=set(['underfull']), 5 | help='Enable/disable warning from CLASS, which can be any package name, ' 6 | 'LaTeX warning class (e.g., font), bad box type ' 7 | - '(underfull, overfull, loose, tight), or "all"') 8 | + '(underfull, overfull, loose, tight), strict parsing (strict-parse), or "all"') 9 | arg_parser.add_argument( 10 | '-O', metavar='DIR', dest='obj_dir', default='latex.out', 11 | help='Directory for intermediate files and control database ' 12 | @@ -236,6 +236,21 @@ def mkdir_p(path): 13 | pass 14 | else: raise 15 | 16 | +def nested_parenthesis_end(string, opening, closing, lax_checking=False): 17 | + """Return index where closing character corresponds to opening character""" 18 | + stack = [] 19 | + for i, c in enumerate(string): 20 | + if c in opening: 21 | + stack.append(c) 22 | + elif c in closing and stack: 23 | + start_ch = stack.pop() 24 | + if not lax_checking and opening.index(start_ch) != closing.index(c): 25 | + # Mismatch, e.g. expected ')', found '}' 26 | + return -1 27 | + if not stack: 28 | + return i 29 | + return -1 30 | + 31 | class DB: 32 | """A latexrun control database.""" 33 | 34 | @@ -1288,16 +1303,18 @@ class LaTeXFilter: 35 | self.__file_stack.pop() 36 | else: 37 | self.__message('warning', None, 38 | - "extra `)' in log; file names may be wrong ") 39 | + "extra `)' in log; file names may be wrong") 40 | elif ch == '{': 41 | # TeX uses this for various things we want to ignore, like 42 | # file names and print_mark. Consume up to the '}' 43 | - epos = self.__data.find('}', self.__pos) 44 | - if epos != -1: 45 | - self.__pos = epos + 1 46 | - else: 47 | + lax_checking = "strict-parse" in self.__suppress 48 | + epos = nested_parenthesis_end(self.__data[self.__pos-1:], '{[(', '}])', 49 | + lax_checking=lax_checking) 50 | + if epos == -1: 51 | self.__message('warning', None, 52 | "unbalanced `{' in log; file names may be wrong") 53 | + else: 54 | + self.__pos += epos 55 | elif ch == '}': 56 | self.__message('warning', None, 57 | "extra `}' in log; file names may be wrong") 58 | @@ -1439,14 +1456,15 @@ class LaTeXFilter: 59 | return 60 | # Back up to the end of the known message text 61 | self.__pos = origpos + m.end() 62 | - if self.__lookingat('\n'): 63 | + if self.__lookingatre(r'\s*\n'): 64 | # We have a newline, so consume it and look for the 65 | # offending text. 66 | self.__pos += 1 67 | # If there is offending text, it will start with a font 68 | # name, which will start with a \. 69 | - if 'hbox' in msg and self.__lookingat('\\'): 70 | - self.__consume_line(unwrap=True) 71 | + if 'hbox' in msg and self.__lookingatre(r'(\[\]\s?)*\s*\\'): 72 | + consumed = self.__consume_line(unwrap=True) 73 | + if self.TRACE: print('consuming `<{}>\''.format(consumed)) 74 | msg = self.__simplify_message(msg) + ' (page {})'.format(self.__pageno) 75 | cls = msg.split(None, 1)[0].lower() 76 | self.__message('warning', lineno, msg, cls=cls) 77 | -------------------------------------------------------------------------------- /patches/latexrun-pull-47: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -861,15 +861,16 @@ class LaTeX(Task): 4 | pages of output. 5 | """ 6 | jobname = outname = None 7 | - for m in re.finditer(r'^Transcript written on "?(.*)\.log"?\.$', stdout, 8 | + for m in re.finditer(r'^Transcript written on "?(.*?)\.log"?\.$', stdout, 9 | re.MULTILINE | re.DOTALL): 10 | jobname = m.group(1).replace('\n', '') 11 | if jobname is None: 12 | print(stdout, file=sys.stderr) 13 | raise TaskError('failed to extract job name from latex log') 14 | - for m in re.finditer(r'^Output written on "?(.*\.[^ ."]+)"? \([0-9]+ page', 15 | + for m in re.finditer(r'^Output written on "?(.*?\.[^ ."]+)"? \([0-9]+ (page)?', 16 | stdout, re.MULTILINE | re.DOTALL): 17 | - outname = m.group(1).replace('\n', '') 18 | + if m.group(2) == "page": 19 | + outname = m.group(1).replace('\n', '') 20 | if outname is None and not \ 21 | re.search(r'^No pages of output\.$|^! Emergency stop\.$' 22 | r'|^! ==> Fatal error occurred, no output PDF file produced!$', 23 | -------------------------------------------------------------------------------- /patches/latexrun-pull-52: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -763,7 +763,8 @@ class LaTeX(Task): 4 | p = subprocess.Popen(args, 5 | stdin=subprocess.DEVNULL, 6 | stdout=subprocess.PIPE, 7 | - stderr=subprocess.STDOUT) 8 | + stderr=subprocess.STDOUT, 9 | + env={**os.environ, 'max_print_line': '2147483647'}) 10 | stdout, has_errors, missing_includes = self.__feed_terminal(p.stdout) 11 | status = p.wait() 12 | except OSError as e: 13 | @@ -1171,19 +1172,6 @@ class LaTeXFilter: 14 | self.__ensure_line() 15 | data = self.__data[self.__pos:self.__lend] 16 | self.__pos = self.__lend 17 | - if unwrap: 18 | - # TeX helpfully wraps all terminal output at 79 columns 19 | - # (max_print_line). If requested, unwrap it. There's 20 | - # simply no way to do this perfectly, since there could be 21 | - # a line that happens to be 79 columns. 22 | - # 23 | - # We check for >=80 because a bug in LuaTeX causes it to 24 | - # wrap at 80 columns instead of 79 (LuaTeX #900). 25 | - while self.__lend - self.__lstart >= 80: 26 | - if self.TRACE: print('<{}> wrapping'.format(self.__pos)) 27 | - self.__ensure_line() 28 | - data = data[:-1] + self.__data[self.__pos:self.__lend] 29 | - self.__pos = self.__lend 30 | return data 31 | 32 | # Parser productions 33 | -------------------------------------------------------------------------------- /patches/latexrun-pull-61: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -457,10 +457,12 @@ class Message(collections.namedtuple( 4 | 'Message', 'typ filename lineno msg')): 5 | def emit(self): 6 | if self.filename: 7 | - if self.filename.startswith('./'): 8 | - finfo = self.filename[2:] 9 | - else: 10 | + cwd = os.getcwd() 11 | + if (os.path.isabs(self.filename) and 12 | + os.path.commonpath([self.filename, cwd]) != cwd): 13 | finfo = self.filename 14 | + else: 15 | + finfo = os.path.relpath(self.filename, cwd) 16 | else: 17 | finfo = '' 18 | if self.lineno is not None: 19 | -------------------------------------------------------------------------------- /patches/latexrun-pull-62: -------------------------------------------------------------------------------- 1 | --- latexrun 2 | +++ latexrun 3 | @@ -965,7 +965,7 @@ class LaTeX(Task): 4 | 5 | def __clean_messages(self, msgs): 6 | """Make some standard log messages more user-friendly.""" 7 | - have_undefined_reference = False 8 | + has_errors = any(msg.typ == 'error' for msg in msgs) 9 | for msg in msgs: 10 | if msg.msg == '==> Fatal error occurred, no output PDF file produced!': 11 | msg = msg._replace(typ='info', 12 | @@ -973,10 +973,15 @@ class LaTeX(Task): 13 | if msg.msg.startswith('[LaTeX] '): 14 | # Strip unnecessary package name 15 | msg = msg._replace(msg=msg.msg.split(' ', 1)[1]) 16 | - if re.match(r'Reference .* undefined', msg.msg): 17 | - have_undefined_reference = True 18 | - if have_undefined_reference and \ 19 | - re.match(r'There were undefined references', msg.msg): 20 | + if has_errors and re.match( 21 | + r'.*[Rr]erun to get .* right|.* on page .* undefined', msg.msg 22 | + ): 23 | + # Warnings on undefined references may occur in high 24 | + # numbers when documents fail to build. 25 | + continue 26 | + if re.match( 27 | + r"There were (multiply-defined labels|undefined references)", msg.msg 28 | + ): 29 | # LaTeX prints this at the end so the user knows it's 30 | # worthwhile looking back at the log. Since latexrun 31 | # makes the earlier messages obvious, this is 32 | -------------------------------------------------------------------------------- /repositories.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | Setup of all the LaTeX dependencies. 3 | """ 4 | 5 | load( 6 | "@bazel_latex//:texlive_2022_repos.bzl", 7 | "TEXLIVE_MODULAR_PACKAGES_BIN_2022", 8 | "TEXLIVE_MODULAR_PACKAGES_OTHER_2022", 9 | "TEXLIVE_VERSION_2022", 10 | ) 11 | load("@bazel_latex//:version.bzl", "texlive_version") 12 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 13 | 14 | bin_build_file = """ 15 | # {} 16 | 17 | exports_files( 18 | glob(["*.*", "*"]), 19 | visibility = ["//visibility:public"], 20 | ) 21 | """ 22 | 23 | other_build_file = """ 24 | 25 | exports_files( 26 | glob(["*.*", "*"]), 27 | visibility = ["//visibility:public"], 28 | ) 29 | 30 | filegroup( 31 | name = "{}", 32 | srcs = glob( 33 | include = ["**"], 34 | exclude = [ 35 | "BUILD.bazel", 36 | "WORKSPACE", 37 | ], 38 | ), 39 | visibility = ["//visibility:public"], 40 | ) 41 | """ 42 | 43 | # This allows us to append versions and keep mutliple version alive instead of 44 | # forcing users to use an older version of this repo just to use and older 45 | # version of latex. 46 | LATEX_DIST = { 47 | TEXLIVE_VERSION_2022: struct( 48 | bin = TEXLIVE_MODULAR_PACKAGES_BIN_2022, 49 | other = TEXLIVE_MODULAR_PACKAGES_OTHER_2022, 50 | ), 51 | #TEXLIVE_VERSION_2023: struct(..., 52 | #TEXLIVE_VERSION_40000: struct(..., 53 | } 54 | 55 | def download_pkg_archive(build_file_content, version, path, sha256, patches = [], patch_cmds = []): 56 | """ 57 | Helper function for downloads of external dependencies. 58 | 59 | Args: 60 | build_file_content: The build file content 61 | version: The version of the toolchain to use 62 | path: The path to use 63 | sha256: The checksum to use 64 | patches: The optional patches to apply 65 | patch_cmds: The optional patch commands to apply 66 | """ 67 | modular_url_stem = "https://github.com/ProdriveTechnologies/texlive-modular" 68 | modular_url = "/releases/download/%s/texlive-%s-%s.tar.xz" 69 | name = "texlive_%s" % path.replace("/", "__") 70 | http_archive( 71 | name = name, 72 | build_file_content = build_file_content.format(name), 73 | patches = patches, 74 | patch_cmds = patch_cmds, 75 | sha256 = sha256, 76 | url = modular_url_stem + modular_url % (version, version, path.replace("/", "--")), 77 | ) 78 | 79 | _alias_rule_template = """ 80 | alias( 81 | name = "{name}", 82 | actual = "{actual}", 83 | visibility = ["//visibility:public"], 84 | tags = ["manual"], 85 | ) 86 | """ 87 | 88 | def _repository_alias_impl(rctx): 89 | rctx.file("BUILD.bazel", "\n".join([_alias_rule_template.replace("{name}", f).replace("{actual}", "@{}".format(f)) for f in rctx.attr.alias_list])) 90 | 91 | _repository_alias = repository_rule( 92 | implementation = _repository_alias_impl, 93 | attrs = { 94 | "alias_list": attr.string_list(), 95 | }, 96 | ) 97 | 98 | def latex_texlive_repositories(version): 99 | """ 100 | Load all the texlive repositories. 101 | 102 | Args: 103 | version: version of texlive. See the LATEX_DIST variable. 104 | """ 105 | if version not in LATEX_DIST: 106 | fail("Available texlive dists are: {}".format(LATEX_DIST.keys())) 107 | pkgs = LATEX_DIST[version] 108 | 109 | other = [ent[0] for ent in pkgs.other] 110 | texlive_version(name = "texlive_version", version = ":../../".join(other)) 111 | 112 | for path, sha256, patches in pkgs.bin: 113 | download_pkg_archive(bin_build_file, version, path, sha256, patches) 114 | 115 | for path, sha256, patches in pkgs.other: 116 | download_pkg_archive(other_build_file, version, path, sha256, patches) 117 | 118 | _repository_alias(name = "bazel_latex_texlive", alias_list = ["texlive_%s" % f.replace("/", "__") for f in other]) 119 | 120 | def _latex_run_repository(): 121 | http_archive( 122 | name = "bazel_latex_latexrun", 123 | build_file_content = """ 124 | py_binary( 125 | name = "latexrun", 126 | srcs = ["latexrun.py"], 127 | visibility = ["//visibility:public"], 128 | )""", 129 | patches = [ 130 | "@bazel_latex//:patches/latexrun-force-colors", 131 | "@bazel_latex//:patches/latexrun-pull-21", 132 | "@bazel_latex//:patches/latexrun-pull-47", 133 | "@bazel_latex//:patches/latexrun-pull-52", 134 | "@bazel_latex//:patches/latexrun-pull-61", 135 | "@bazel_latex//:patches/latexrun-pull-62", 136 | ], 137 | patch_cmds = [ 138 | "mv latexrun latexrun.py", 139 | ], 140 | sha256 = "4e1512fde5a05d1249fd6b4e6610cdab8e14ddba82a7cbb58dc7d5c0ba468c2a", 141 | strip_prefix = "latexrun-38ff6ec2815654513c91f64bdf2a5760c85da26e", 142 | url = "https://github.com/aclements/latexrun/archive/38ff6ec2815654513c91f64bdf2a5760c85da26e.tar.gz", 143 | ) 144 | 145 | def _platforms_repository(): 146 | http_archive( 147 | name = "platforms", 148 | urls = [ 149 | "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.6/platforms-0.0.6.tar.gz", 150 | "https://github.com/bazelbuild/platforms/releases/download/0.0.6/platforms-0.0.6.tar.gz", 151 | ], 152 | sha256 = "5308fc1d8865406a49427ba24a9ab53087f17f5266a7aabbfc28823f3916e1ca", 153 | ) 154 | 155 | def _rules_foreign_cc_repository(): 156 | http_archive( 157 | name = "rules_foreign_cc", 158 | sha256 = "2a4d07cd64b0719b39a7c12218a3e507672b82a97b98c6a89d38565894cf7c51", 159 | strip_prefix = "rules_foreign_cc-0.9.0", 160 | url = "https://github.com/bazelbuild/rules_foreign_cc/archive/refs/tags/0.9.0.tar.gz", 161 | ) 162 | 163 | def _ghost_script_repository(): 164 | _ALL_CONTENT = """\ 165 | filegroup( 166 | name = "all_srcs", 167 | srcs = glob(["**"]), 168 | visibility = ["//visibility:public"], 169 | ) 170 | """ 171 | 172 | http_archive( 173 | name = "ghost_script_source", 174 | sha256 = "6bf362286e359e31f934e5aad49db3d88a2382a3cac44b40572861ee5c536664", 175 | strip_prefix = "ghostpdl-9.56.1", 176 | build_file_content = _ALL_CONTENT, 177 | url = "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs9561/ghostpdl-9.56.1.tar.gz", 178 | ) 179 | 180 | def latex_repositories(version = TEXLIVE_VERSION_2022): 181 | """ 182 | Load all the dependencies required to compile LaTeX documents. 183 | 184 | Args: 185 | version: version of texlive. See the LATEX_DIST variable. 186 | """ 187 | 188 | latex_texlive_repositories(version) 189 | _latex_run_repository() 190 | _platforms_repository() 191 | _rules_foreign_cc_repository() 192 | _ghost_script_repository() 193 | 194 | def _module_repositories_impl(mctx): 195 | _latex_run_repository() 196 | _ghost_script_repository() 197 | return mctx.extension_metadata(reproducible = True) 198 | 199 | module_repositories = module_extension( 200 | implementation = _module_repositories_impl, 201 | ) 202 | -------------------------------------------------------------------------------- /requirements.in: -------------------------------------------------------------------------------- 1 | beautifulsoup4 == 4.11.2 2 | lxml == 4.9.2 3 | pypdf == 3.5.0 4 | reportlab == 3.6.13 5 | svglib == 1.5.1 6 | -------------------------------------------------------------------------------- /requirements_lock.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.11.2 2 | cssselect2==0.7.0 3 | lxml==4.9.2 4 | pillow==10.4.0 5 | pypdf==3.5.0 6 | reportlab==3.6.13 7 | soupsieve==2.6 8 | svglib==1.5.1 9 | tinycss2==1.3.0 10 | webencodings==0.5.1 11 | -------------------------------------------------------------------------------- /third_party/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_foreign_cc//foreign_cc:defs.bzl", "configure_make") 2 | 3 | configure_make( 4 | name = "lib_ghost_script_configure_linux", 5 | autoreconf = True, 6 | autoreconf_options = ["-fi"], 7 | configure_in_place = True, 8 | install_prefix = "output", 9 | lib_source = "@ghost_script_source//:all_srcs", 10 | # libgs compilation currently fails to build on mac os x latest 11 | out_shared_libs = ["libgs.so"], 12 | target_compatible_with = ["@platforms//os:linux"], 13 | targets = [ 14 | "so", 15 | "soinstall", 16 | ], 17 | visibility = ["//visibility:public"], 18 | ) 19 | 20 | filegroup( 21 | name = "libgs", 22 | srcs = [":lib_ghost_script_configure_linux"], 23 | visibility = ["//visibility:public"], 24 | ) 25 | -------------------------------------------------------------------------------- /toolchain.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | Definitions related to a LaTeX toolchain 3 | """ 4 | 5 | LatexInfo = provider( 6 | doc = "Information about how to invoke the latex compiler", 7 | fields = [ 8 | "biber", 9 | "bibtex", 10 | "dvisvgm", 11 | "gsftopk", 12 | "kpsewhich", 13 | "kpsestat", 14 | "luahbtex", 15 | "luatex", 16 | "mktexlsr", 17 | "kpseaccess", 18 | ], 19 | ) 20 | 21 | def _latex_toolchain_info_impl(ctx): 22 | return [ 23 | platform_common.ToolchainInfo( 24 | latexinfo = LatexInfo( 25 | biber = ctx.attr.biber, 26 | bibtex = ctx.attr.bibtex, 27 | dvisvgm = ctx.attr.dvisvgm, 28 | gsftopk = ctx.attr.gsftopk, 29 | kpsewhich = ctx.attr.kpsewhich, 30 | kpsestat = ctx.attr.kpsestat, 31 | luahbtex = ctx.attr.luahbtex, 32 | luatex = ctx.attr.luatex, 33 | mktexlsr = ctx.attr.mktexlsr, 34 | kpseaccess = ctx.attr.kpseaccess, 35 | ), 36 | ), 37 | ] 38 | 39 | _latex_toolchain_info = rule( 40 | attrs = { 41 | "biber": attr.label( 42 | allow_single_file = True, 43 | cfg = "exec", 44 | executable = True, 45 | ), 46 | "bibtex": attr.label( 47 | allow_single_file = True, 48 | cfg = "exec", 49 | executable = True, 50 | ), 51 | "dvisvgm": attr.label( 52 | allow_single_file = True, 53 | cfg = "exec", 54 | executable = True, 55 | ), 56 | "gsftopk": attr.label( 57 | allow_single_file = True, 58 | cfg = "exec", 59 | executable = True, 60 | ), 61 | "kpseaccess": attr.label( 62 | allow_single_file = True, 63 | cfg = "exec", 64 | executable = True, 65 | ), 66 | "kpsestat": attr.label( 67 | allow_single_file = True, 68 | cfg = "exec", 69 | executable = True, 70 | ), 71 | "kpsewhich": attr.label( 72 | allow_single_file = True, 73 | cfg = "exec", 74 | executable = True, 75 | ), 76 | "luahbtex": attr.label( 77 | allow_single_file = True, 78 | cfg = "exec", 79 | executable = True, 80 | ), 81 | "luatex": attr.label( 82 | allow_single_file = True, 83 | cfg = "exec", 84 | executable = True, 85 | ), 86 | "mktexlsr": attr.label( 87 | allow_single_file = True, 88 | cfg = "exec", 89 | executable = True, 90 | ), 91 | }, 92 | implementation = _latex_toolchain_info_impl, 93 | ) 94 | 95 | def latex_toolchain(platform, exec_compatible_with, name = None): 96 | """ 97 | Defines a LaTeX toolchain. 98 | 99 | Args: 100 | name: optional name for the toolchain, defaults to latex_toolchain_{platform}. 101 | platform: name of the platform as named by TeXLive. 102 | exec_compatible_with: execution constraints passed to the toolchain. 103 | """ 104 | _toolchain_name = name if name != None else "latex_toolchain_%s" % platform 105 | 106 | stem = "@texlive_bin__" + platform + "//:" 107 | _latex_toolchain_info( 108 | name = "%s_info" % _toolchain_name, 109 | biber = stem + "biber", 110 | bibtex = stem + "bibtex", 111 | dvisvgm = stem + "dvisvgm", 112 | gsftopk = stem + "gsftopk", 113 | kpseaccess = stem + "kpseaccess", 114 | kpsestat = stem + "kpsestat", 115 | kpsewhich = stem + "kpsewhich", 116 | luahbtex = stem + "luahbtex", 117 | luatex = stem + "luatex", 118 | mktexlsr = "@texlive_texmf__texmf-dist__scripts__texlive//:" + "mktexlsr", 119 | visibility = ["//visibility:public"], 120 | ) 121 | 122 | native.toolchain( 123 | name = _toolchain_name, 124 | exec_compatible_with = exec_compatible_with, 125 | toolchain = ":%s_info" % _toolchain_name, 126 | toolchain_type = ":latex_toolchain_type", 127 | ) 128 | -------------------------------------------------------------------------------- /tools/compute_dependencies/.gitignore: -------------------------------------------------------------------------------- 1 | /input.tex 2 | /BUILD.bazel 3 | -------------------------------------------------------------------------------- /tools/compute_dependencies/compute_dependencies.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # compute_dependencies: Find minimal dependencies of a LaTeX document. 4 | # 5 | # This script invokes Bazel repeatedly to determine the minimal set of 6 | # dependencies of a LaTeX document, using a binary searching approach. 7 | # This may be useful when creating Bazel targets for packages. 8 | 9 | import hashlib 10 | import subprocess 11 | import sys 12 | 13 | # Obtain full list of texmf externals provided by TeXLive. 14 | with subprocess.Popen( 15 | ["bazel", "query", "//external:*"], stdout=subprocess.PIPE 16 | ) as proc: 17 | all_externals = frozenset( 18 | "@" + external[11:].strip().decode("ascii") 19 | for external in proc.stdout.readlines() 20 | if external.startswith(b"//external:texlive_texmf__") 21 | ) 22 | 23 | 24 | def build(externals): 25 | """Build a document with given externals and return its checksum.""" 26 | with open("BUILD.bazel", "wb") as f: 27 | with subprocess.Popen( 28 | ["buildifier"], stdin=subprocess.PIPE, stdout=f, encoding="ascii" 29 | ) as proc: 30 | proc.stdin.write( 31 | """load("//:latex.bzl", "latex_document") 32 | 33 | latex_document( 34 | name = "output", 35 | main = "input.tex", 36 | srcs = %s, 37 | )""" 38 | % repr(sorted(externals)) 39 | ) 40 | if subprocess.call(["bazel", "build", ":output"]) != 0: 41 | return None 42 | checksum = hashlib.sha256() 43 | with open("../../bazel-bin/tools/compute_dependencies/output.pdf", "rb") as f: 44 | while True: 45 | data = f.read(4096) 46 | if not data: 47 | break 48 | checksum.update(data) 49 | return checksum.digest() 50 | 51 | 52 | # Perform an initial build with all dependencies to determine what the 53 | # resulting document should look like. 54 | desired_checksum = build(all_externals) 55 | if desired_checksum is None: 56 | print("Document doesn't even build with all TeXLive packages in place") 57 | sys.exit(1) 58 | 59 | # Prune unnecessary dependencies using binary searching. 60 | necessary = set(all_externals) 61 | to_check = [all_externals] 62 | while to_check: 63 | l = to_check.pop(0) 64 | print(len(l)) 65 | if build(necessary - l) == desired_checksum: 66 | # Removing the externals did not affect output, meaning these 67 | # aren't actual dependencies. 68 | necessary -= l 69 | elif len(l) > 1: 70 | # Removing the externals broke the build or changed the output. 71 | # Decompose the sets to see which externals caused this. 72 | sl = sorted(l) 73 | to_check.append(frozenset(sl[: len(l) // 2])) 74 | to_check.append(frozenset(sl[len(l) // 2 :])) 75 | 76 | # Emit a final copy of BUILD.bazel with the definitive list of 77 | # dependencies. 78 | if build(necessary) != desired_checksum: 79 | print("Final build yielded a different checksum") 80 | -------------------------------------------------------------------------------- /version.bzl: -------------------------------------------------------------------------------- 1 | """ 2 | This modules allows ourselves to share and readup the used texlive version. 3 | """ 4 | 5 | def _version_impl(ctx): 6 | ctx.file("BUILD.bazel", "") 7 | ctx.file("texlive_version.bzl", "TEXLIVE_VERSION=[{}]".format(ctx.attr.version.split(":"))) 8 | 9 | texlive_version = repository_rule( 10 | implementation = _version_impl, 11 | attrs = { 12 | "version": attr.string(doc = "The texlive version"), 13 | }, 14 | ) 15 | -------------------------------------------------------------------------------- /view_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | filename="$1" 3 | stderr_type="$2" 4 | 5 | if type xdg-open > /dev/null 2>&1; then 6 | # X11-based systems (Linux, BSD). 7 | 8 | if [ "$stderr_type" = "None" ] ; then 9 | exec xdg-open "${filename}" 2>/dev/null & 10 | else 11 | exec xdg-open "${filename}" & 12 | fi 13 | 14 | elif type open > /dev/null 2>&1; then 15 | # macOS. 16 | exec open "${filename}" 17 | else 18 | echo "Don't know how to view PDFs on this platform." >&2 19 | exit 1 20 | fi 21 | --------------------------------------------------------------------------------