summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/minim
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-06-10 03:01:49 +0000
committerNorbert Preining <norbert@preining.info>2021-06-10 03:01:49 +0000
commit2bd77f5a4d02b0d1649589aa7a548e79b198f6af (patch)
tree04786bcca2c349d0cb1373335978e03bb117df7b /macros/luatex/generic/minim
parentf7fc4ad3995d7f6ebbed20c20bf06e3a9176ea04 (diff)
CTAN sync 202106100301
Diffstat (limited to 'macros/luatex/generic/minim')
-rw-r--r--macros/luatex/generic/minim/EUPL-1.2-EN.txt287
-rw-r--r--macros/luatex/generic/minim/README40
-rw-r--r--macros/luatex/generic/minim/minim-alloc.doc216
-rw-r--r--macros/luatex/generic/minim/minim-alloc.lua196
-rw-r--r--macros/luatex/generic/minim/minim-alloc.tex184
-rw-r--r--macros/luatex/generic/minim/minim-callbacks.lua265
-rw-r--r--macros/luatex/generic/minim/minim-doc.sty215
-rw-r--r--macros/luatex/generic/minim/minim-etex.tex413
-rw-r--r--macros/luatex/generic/minim/minim-hooks.lua30
-rw-r--r--macros/luatex/generic/minim/minim-hooks.tex56
-rw-r--r--macros/luatex/generic/minim/minim-lmodern.tex28
-rw-r--r--macros/luatex/generic/minim/minim-plain.tex786
-rw-r--r--macros/luatex/generic/minim/minim.doc81
-rw-r--r--macros/luatex/generic/minim/minim.ini25
-rw-r--r--macros/luatex/generic/minim/minim.pdfbin0 -> 285949 bytes
-rw-r--r--macros/luatex/generic/minim/minim.tex8
16 files changed, 2830 insertions, 0 deletions
diff --git a/macros/luatex/generic/minim/EUPL-1.2-EN.txt b/macros/luatex/generic/minim/EUPL-1.2-EN.txt
new file mode 100644
index 0000000000..4153cd3775
--- /dev/null
+++ b/macros/luatex/generic/minim/EUPL-1.2-EN.txt
@@ -0,0 +1,287 @@
+ EUROPEAN UNION PUBLIC LICENCE v. 1.2
+ EUPL © the European Union 2007, 2016
+
+This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
+below) which is provided under the terms of this Licence. Any use of the Work,
+other than as authorised under this Licence is prohibited (to the extent such
+use is covered by a right of the copyright holder of the Work).
+
+The Work is provided under the terms of this Licence when the Licensor (as
+defined below) has placed the following notice immediately following the
+copyright notice for the Work:
+
+ Licensed under the EUPL
+
+or has expressed by any other means his willingness to license under the EUPL.
+
+1. Definitions
+
+In this Licence, the following terms have the following meaning:
+
+- ‘The Licence’: this Licence.
+
+- ‘The Original Work’: the work or software distributed or communicated by the
+ Licensor under this Licence, available as Source Code and also as Executable
+ Code as the case may be.
+
+- ‘Derivative Works’: the works or software that could be created by the
+ Licensee, based upon the Original Work or modifications thereof. This Licence
+ does not define the extent of modification or dependence on the Original Work
+ required in order to classify a work as a Derivative Work; this extent is
+ determined by copyright law applicable in the country mentioned in Article 15.
+
+- ‘The Work’: the Original Work or its Derivative Works.
+
+- ‘The Source Code’: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
+
+- ‘The Executable Code’: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
+
+- ‘The Licensor’: the natural or legal person that distributes or communicates
+ the Work under the Licence.
+
+- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
+
+- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
+ the Work under the terms of the Licence.
+
+- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, online or offline, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
+
+2. Scope of the rights granted by the Licence
+
+The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+sublicensable licence to do the following, for the duration of copyright vested
+in the Original Work:
+
+- use the Work in any circumstance and for all usage,
+- reproduce the Work,
+- modify the Work, and make Derivative Works based upon the Work,
+- communicate to the public, including the right to make available or display
+ the Work or copies thereof to the public and perform publicly, as the case may
+ be, the Work,
+- distribute the Work or copies thereof,
+- lend and rent the Work or copies thereof,
+- sublicense rights in the Work or copies thereof.
+
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
+
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
+
+The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
+
+3. Communication of the Source Code
+
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute or communicate the Work.
+
+4. Limitations on copyright
+
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Work, of the exhaustion of those rights or of other applicable limitations
+thereto.
+
+5. Obligations of the Licensee
+
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
+
+Attribution right: The Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes or communicates copies of the
+Original Works or Derivative Works, this Distribution or Communication will be
+done under the terms of this Licence or of a later version of this Licence
+unless the Original Work is expressly distributed only under this version of the
+Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
+(becoming Licensor) cannot offer or impose any additional terms or conditions on
+the Work or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes or Communicates Derivative
+Works or copies thereof based upon both the Work and another work licensed under
+a Compatible Licence, this Distribution or Communication can be done under the
+terms of this Compatible Licence. For the sake of this clause, ‘Compatible
+Licence’ refers to the licences listed in the appendix attached to this Licence.
+Should the Licensee's obligations under the Compatible Licence conflict with
+his/her obligations under this Licence, the obligations of the Compatible
+Licence shall prevail.
+
+Provision of Source Code: When distributing or communicating copies of the Work,
+the Licensee will provide a machine-readable copy of the Source Code or indicate
+a repository where this Source will be easily and freely available for as long
+as the Licensee continues to distribute or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+Contributors. It is not a finished work and may therefore contain defects or
+‘bugs’ inherent to this type of development.
+
+For the above reason, the Work is provided under the Licence on an ‘as is’ basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such damage.
+However, the Licensor will be liable under statutory product liability laws as
+far such laws apply to the Work.
+
+9. Additional agreements
+
+While distributing the Work, You may choose to conclude an additional agreement,
+defining obligations or services consistent with this Licence. However, if
+accepting obligations, You may act only on your own behalf and on your sole
+responsibility, not on behalf of the original Licensor or any other Contributor,
+and only if You agree to indemnify, defend, and hold each Contributor harmless
+for any liability incurred by, or claims asserted against such Contributor by
+the fact You have accepted any warranty or additional liability.
+
+10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution or Communication by You of the Work or copies thereof.
+
+11. Information to the public
+
+In case of any Distribution or Communication of the Work by means of electronic
+communication by You (for example, by offering to download the Work from a
+remote location) the distribution channel or media (for example, a website) must
+at least provide to the public the information requested by the applicable law
+regarding the Licensor, the Licence and the way it may be accessible, concluded,
+stored and reproduced by the Licensee.
+
+12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed or reformed so as necessary to make it
+valid and enforceable.
+
+The European Commission may publish other linguistic versions or new versions of
+this Licence or updated versions of the Appendix, so far this is required and
+reasonable, without reducing the scope of the rights granted by the Licence. New
+versions of the Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+14. Jurisdiction
+
+Without prejudice to specific agreement between parties,
+
+- any litigation resulting from the interpretation of this License, arising
+ between the European Union institutions, bodies, offices or agencies, as a
+ Licensor, and any Licensee, will be subject to the jurisdiction of the Court
+ of Justice of the European Union, as laid down in article 272 of the Treaty on
+ the Functioning of the European Union,
+
+- any litigation arising between other parties and resulting from the
+ interpretation of this License, will be subject to the exclusive jurisdiction
+ of the competent court where the Licensor resides or conducts its primary
+ business.
+
+15. Applicable Law
+
+Without prejudice to specific agreement between parties,
+
+- this Licence shall be governed by the law of the European Union Member State
+ where the Licensor has his seat, resides or has his registered office,
+
+- this licence shall be governed by Belgian law if the Licensor has no seat,
+ residence or registered office inside a European Union Member State.
+
+Appendix
+
+‘Compatible Licences’ according to Article 5 EUPL are:
+
+- GNU General Public License (GPL) v. 2, v. 3
+- GNU Affero General Public License (AGPL) v. 3
+- Open Software License (OSL) v. 2.1, v. 3.0
+- Eclipse Public License (EPL) v. 1.0
+- CeCILL v. 2.0, v. 2.1
+- Mozilla Public Licence (MPL) v. 2
+- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
+- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
+ works other than software
+- European Union Public Licence (EUPL) v. 1.1, v. 1.2
+- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
+ Reciprocity (LiLiQ-R+).
+
+The European Commission may update this Appendix to later versions of the above
+licences without producing a new version of the EUPL, as long as they provide
+the rights granted in Article 2 of this Licence and protect the covered Source
+Code from exclusive appropriation.
+
+All other changes or additions to this Appendix require the production of a new
+EUPL version.
diff --git a/macros/luatex/generic/minim/README b/macros/luatex/generic/minim/README
new file mode 100644
index 0000000000..4a16b4e801
--- /dev/null
+++ b/macros/luatex/generic/minim/README
@@ -0,0 +1,40 @@
+Version: 2021/1.0
+
+SUMMARY
+
+This is a modern plain format for the LuaTeX engine, adding improved low-level
+support for many LuaTeX extensions and newer PDF features. While it can be
+used as drop-in replacement for plain TeX, it probably is most useful as
+a basis for your own formats.
+
+Most features included in the format are provided by separate packages that
+can be used on their own; see the packages
+
+ minim-mp for mplib (MetaPost) support
+ minim-math for unicode mathematics
+ minim-pdf for creating Tagged PDF
+ minim-xmp for XMP (metadata) inclusion
+
+This package proper only contains their shared lowest-level programming
+interface, together with their combined format.
+
+
+DOCUMENTATION
+
+In order to obtain the typeset manual of this package, simply say:
+
+ luatex minim.doc
+
+For the sake of completeness, this manual also includes the documentation of
+the packages mentioned above.
+
+
+COPYING
+
+(c) 2021 Esger Renkema
+
+These files may be distributed under the terms of the European Union Public
+Licence (EUPL) version 1.2 or later. A copy can be obtained at:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
diff --git a/macros/luatex/generic/minim/minim-alloc.doc b/macros/luatex/generic/minim/minim-alloc.doc
new file mode 100644
index 0000000000..fa08988bf4
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-alloc.doc
@@ -0,0 +1,216 @@
+
+\input minim-doc.sty
+
+This chapter describes the programming helper modules on which all the above
+modules depend. It mainly concerns register allocation, callback management and
+format file inclusion.
+
+They can be loaded separately by saying ⟦\input minim-alloc⟧;
+thereafter, you can use ⟦local M = require('minim-alloc')⟧ to access the lua
+interface.
+In this chapter, when discussing lua functions, you are assumed to have issued
+the latter statement, so that the table ⟦M⟧ refers to the contents of this
+module.
+
+The callback-related code lives in a separate file that can and must be loaded
+separately as ⟦local C = require('minim-callbacks')⟧. This is the only file in
+this collection that does not itself depend on the minim-alloc module.
+
+There is a large functional overlap between this module and the ltluatex
+package. You can use both at the same time, however, and the order in which you
+load both packages should not matter.
+
+\section Format files
+
+A major motivation for writing this module (and not, instead, depending on
+⟦ltluatex.tex⟧) is the ability to write lua-heavy code that can be safely
+included in format files.
+For this purpose, the register allocation functions described below allow
+ensuring that the allocation is made only once.
+
+Apart from registers, you need only do two more things to make your code format
+file safe. The first is saying ⟦*M.remember('your-file.lua')⟧ somewhere,
+anywhere. This will mark your file for inclusion in the format. At the start of
+every job, all remembered files will be executed (in order) and their return
+values will be stored to be retrieved whenever you say ⟦require('your-file')⟧.
+Note that while this feature does not improve speed in any meaningful way, it
+will ensure the lua file used by the format is identical to the one used to
+create it.
+
+It does mean, however, that your file may be executed twice: once when building
+the format and once when the format is used. In most cases (e.g. callback
+registration) this is exactly what you want.
+Sometimes however, you may need to store variable (configurable) data in the
+format file.
+You can do this by saying
+⟦*local t = M.saved_table('identifier', default-table)⟧.
+This will retrieve the table from the format file if possible; otherwise, it
+will return ⟦default-table⟧ and mark it to be saved to the format. A missing
+second argument is equivalent to an empty table.
+Saved tables may only contain (arbitrary but non-cyclic nestings of) tables,
+numbers and strings.
+
+\section Register allocation
+
+For allocating the new luatex registers, you can use the following:
+⟦*\newfunction⟧,
+⟦*\newattribute⟧,
+⟦*\newwhatsit⟧,
+⟦*\newluabytecode⟧,
+⟦*\newluachunkname⟧,
+⟦*\newcatcodetable⟧ and
+⟦*\newuserrule⟧.
+Note the one difference with ltluatex, which has ⟦\newluafunction⟧ instead.
+(The reason for this is that ltluatex, instead of a more sensible method, uses
+this macro for determining whether it has been read before.)
+Internally, the very same counts are used for keeping track of register
+allocation as in ltluatex.
+Their effect should therefore be identical in all circumstances, with one
+exception:
+no bounds checking is performed on any allocation macro defined by minim.
+Please do not go and use more than sixty five thousand different whatsits.
+
+All the above and all traditional registers can be allocated from within lua as
+well, using ⟦*M.new_count('name')⟧, ⟦*M.new_whatsit('name')⟧ etc. All return
+the allocated number. The (optional) string ⟦name⟧ prevents the same allocation
+from being made twice: if another register has been retrieved with the same
+name, the number of that register will be returned. You will need this when you
+want to allow your lua code to be included in a format file; it has nothing to
+do with the tex-side ⟦\countdef⟧ and the like.
+
+For the new allocation macros listed above and (as a special case) for
+⟦\newbox⟧,
+after saying ⟦\newwhatsit\name⟧, the call ⟦M.new_whatsit('name')⟧ will return
+the number of ⟦\name⟧. For the other (older) allocation macros, this is not the
+case. After all, because of the ⟦\countdef⟧ etc. included in ⟦\newcount⟧ etc.
+you can already use ⟦tex.count['name']⟧ etc. for retrieving tex-side
+allocations from lua. The exceptions to this are ⟦\newbox⟧, which is why it is
+included with the new macros, and ⟦\newattribute⟧, for which you can use both
+methods.
+
+Besides ⟦\newluachunkname\name⟧, you can also use
+⟦*\setluachunkname \name {actual name}⟧
+to enter the value of the name directly.
+
+Finally, for the registers for which etex defines a local allocation macro (and
+for those only), you can use ⟦*M.local_count()⟧ etc. These allocation functions
+take no parameters.
+
+
+\section Callbacks
+
+As noted at the beginning of this chapter, the callback functions are only
+available after you say ⟦local C = require('minim-callbacks')⟧.
+
+This module will override the primitive callback functions with its own
+⟦*C.register⟧, ⟦*C.find⟧ and ⟦*C.list⟧; the original primitive functions can be
+found in the ⟦*C.primitives⟧ table.
+
+The simple function of this module is allowing multiple callbacks to co-exist.
+Different callbacks call for different implementations, and some callbacks can
+only contain a single function.
+Any callbacks that are already assigned before loading this module will be
+preserved; this includes the ltluatex callback mechanism if it has already been
+installed.
+
+You can create your own callbacks with ⟦*C.new_callback(name, type)⟧. The ⟦type⟧
+should be one of the types mentioned below or ⟦'single'⟧ for callbacks that
+allow only one function. If the ⟦name⟧ is that of a primitive callback, new
+registrations will target your new callback.
+You can call the new callback with ⟦*C.call_callback(name, ...)⟧, adding any
+number of parameters.
+
+Callbacks of type ⟦*node⟧ operate on a node list: for these, all registered
+functions will be called in order, each function receiving the result of the
+last.
+After one function returns ⟦false⟧, no others will be called.
+Callbacks of this type are
+⟦pre_linebreak_filter⟧,
+⟦post_linebreak_filter⟧,
+⟦hpack_filter⟧,
+⟦vpack_filter⟧,
+⟦pre_output_filter⟧ and
+⟦mlist_to_mlist⟧.
+There is no way of unregistering callbacks of this type.
+
+Similarly, for the ⟦*data⟧ callbacks
+⟦process_input_buffer⟧,
+⟦process_output_buffer⟧ and
+⟦process_jobname⟧,
+all registered functions will be called in order on the output of the previous.
+Returning ⟦false⟧ will in this case result in the output of the previous
+function passing to the next.
+
+For ⟦*stack⟧ callbacks, a stack is kept and only the top function on the stack
+will be called. These are
+⟦mlist_to_hlist⟧,
+⟦hpack_quality⟧,
+⟦vpack_quality⟧,
+⟦hyphenate⟧,
+⟦linebreak_filter⟧,
+⟦buildpage_filter⟧ and
+⟦build_page_insert⟧.
+Register ⟦nil⟧ at the callback to pop a function off the stack.
+
+Finally, for the ⟦*simple⟧ callbacks
+⟦contribute_filter⟧,
+⟦pre_dump⟧,
+⟦wrapup_run⟧,
+⟦finish_pdffile⟧,
+⟦finish_pdfpage⟧,
+⟦insert_local_par⟧,
+⟦ligaturing⟧,
+⟦kerning⟧ and
+⟦process_rule⟧.
+all registered functions are called in order with the same arguments.
+
+The new ⟦*mlist_to_mlist⟧ callback is called before ⟦mlist_to_hlist⟧ and should
+not convert noads to nodes.
+
+If you create a new callback with a number for a name, that callback will
+replace the ⟦*process_rule⟧ callback when its number matches the index property
+of the rule.
+
+
+\section Miscellaneous functions
+
+This section describes functions and macros that are internal to this package,
+but might be of general usefulness.
+
+For instance, you might find the function ⟦*M.table_to_text(table)⟧ useful when
+debugging lua code.
+The small functions
+⟦*M.msg(...)⟧, ⟦*M.log(...)⟧ and ⟦*M.err(...)⟧
+include a call to ⟦M.string.format⟧;
+additionally,
+⟦*M.amsg(...)⟧ and ⟦*M.alog(...)⟧
+do not start a new line.
+
+Very useful is ⟦*M.luadef('csname', function, ...)⟧ for defining primitive-like
+tex macros from lua: ⟦function⟧ can be any function (it will be assigned a lua
+function register) and at the place of the dots you may append ⟦'protected'⟧
+and/or ⟦'global'⟧.
+
+Both ⟦*M.unset⟧ and ⟦*\unset⟧ contain the value ⟦-0x7FFFFFFF⟧ that can be used
+for clearing attributes.
+
+On the tex side, ⟦*\voidbox⟧, ⟦*\ignore⟧, ⟦*\spacechar⟧, ⟦*\unbrace⟧,
+⟦*\firstoftwo⟧ and ⟦*\secondoftwo⟧ should be self-explanatory and
+uncontroversial additions. For looking ahead, you can use
+⟦*\nextif \token {executed if present} {executed if not}⟧
+or its siblings ⟦*\nextifx⟧ and ⟦*\nextifcat⟧.
+For defining macros with optional arguments, ⟦*\withoptions[default]{code}⟧
+will ensure something within square brackets follows ⟦code⟧.
+
+Finally, ⟦*\splitcommalist {code} {list}⟧ will apply ⟦code⟧ to every nonempty
+item on a comma-separated ⟦list⟧.
+Items of the list will be re-tokenised and have surrounding spaces removed.
+This macro is fully expandable.
+
+Because of their usefulness and simplicity, these macros have been made
+available without special characters in their names; I hope you can tolerate
+their presence. Please let me know if their names clash with something
+important.
+
+\endinput
+
diff --git a/macros/luatex/generic/minim/minim-alloc.lua b/macros/luatex/generic/minim/minim-alloc.lua
new file mode 100644
index 0000000000..c99ca2c73d
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-alloc.lua
@@ -0,0 +1,196 @@
+
+local M = {}
+
+-- 1 messages
+
+function M.msg(...)
+ texio.write_nl(string.format(...))
+end
+
+function M.amsg(...)
+ texio.write(string.format(...))
+end
+
+function M.log(...)
+ texio.write_nl('log', string.format(...))
+end
+
+function M.alog(...)
+ texio.write('log', string.format(...))
+end
+
+function M.term(...)
+ texio.write_nl('term', string.format(...))
+end
+
+function M.err (...)
+ tex.error(string.format(...))
+end
+
+-- 1 saving modules and tables
+
+local tables = package.loaded['minim-saved-tables']
+ or { ['minim:modules'] = { } }
+local modules = tables ['minim:modules']
+
+function M.remember (name)
+ if modules[name] == nil then
+ modules[name] = false -- will be a number if a bytecode register is reserved
+ modules[#modules+1] = name
+ end
+end
+
+function M.saved_table (identifier, table)
+ if tables[identifier] == nil then
+ tables[identifier] = table or { }
+ end
+ return tables[identifier]
+end
+
+-- saved tables may only contain values that can be converted to and from
+-- strings with tostring() or other tables meeting the same requirement.
+function M.table_to_text (tbl)
+ local r = { }
+ for i,t in pairs(tbl) do
+ local l = ''
+ if type(i) == 'string' then
+ l = string.format('[%q] = ', i)
+ else
+ l = string.format('[%s] = ', i)
+ end
+ if type(t) == 'table' then
+ l = l .. M.table_to_text (t)
+ elseif type(t) == 'string' then
+ l = l .. string.format ('%q', t)
+ else
+ l = l .. tostring(t)
+ end
+ r[#r+1] = l
+ end
+ return '{ ' .. table.concat (r,', ') .. ' }'
+end
+
+require('minim-callbacks')
+M.remember('minim-callbacks')
+M.remember('minim-alloc')
+
+-- 1 allocation functions
+
+-- like \unset
+M.unset = -0x7FFFFFFF
+
+local allocations = M.saved_table ('minim:allocations')
+
+local function make_alloc_new (fname, globcount)
+ allocations[fname] = allocations[fname] or { }
+ M['new_'..fname] = function (id)
+ local nr
+ if id and allocations[fname][id] then
+ nr = allocations[fname][id]
+ else
+ nr = tex.count[globcount] + 1
+ tex.setcount('global', globcount, nr)
+ if id then allocations[fname][id] = nr end
+ M.log('\\%s%d : %s', fname, nr, id or '<unnamed>')
+ end
+ return nr
+ end
+end
+
+make_alloc_new ('attribute' , 'e@alloc@attribute@count' )
+make_alloc_new ('whatsit' , 'e@alloc@whatsit@count' )
+make_alloc_new ('luabytecode' , 'e@alloc@bytecode@count' )
+make_alloc_new ('function' , 'e@alloc@luafunction@count' )
+make_alloc_new ('luachunkname' , 'e@alloc@luachunk@count' )
+make_alloc_new ('catcodetable' , 'e@alloc@ccodetable@count' )
+make_alloc_new ('userrule' , 'e@alloc@rule@count' )
+
+-- We need different allocation functions for the older registers, because
+-- etex’s global allocation macros are off-by-one w.r.t. all other.
+--
+local function make_alloc_old (fname, globcount, loccount)
+ allocations[fname] = allocations[fname] or { }
+ M['new_'..fname] = function (id)
+ local nr
+ if id and allocations[fname][id] then
+ nr = allocations[fname][id]
+ else
+ nr = tex.count[globcount]
+ tex.setcount('global', globcount, nr + 1)
+ if id then allocations[fname][id] = nr end
+ M.log('\\%s%d : %s', fname, nr, id or '<unnamed>')
+ end
+ return nr
+ end
+ M['local_'..fname] = function ()
+ local nr = tex.count[loccount] - 1
+ tex.setcount(loccount, nr)
+ return nr
+ end
+end
+
+-- existing allocation counters
+make_alloc_old ('count', 260, 270 )
+make_alloc_old ('dimen', 261, 271 )
+make_alloc_old ('skip', 262, 272 )
+make_alloc_old ('muskip', 263, 273 )
+make_alloc_old ('box', 264, 274 )
+make_alloc_old ('toks', 265, 275 )
+make_alloc_old ('marks', 266, 276 )
+
+function M.luadef (csname, fn, ...)
+ local nr = M.new_function(csname)
+ lua.get_functions_table()[nr] = fn
+ token.set_lua(csname, nr, ...)
+end
+
+M.luadef ('minim:rememberalloc', function()
+ allocations[token.scan_string()][token.scan_string()] = tex.count['allocationnumber']
+end)
+
+-- 1 dumping information to the format file
+
+-- reserve a bytecode register
+local saved_tables_bytecode = M.new_luabytecode('saved_tables_bytecode')
+
+-- we cannot use set_lua because lua functions are not included in the format file
+token.set_macro('minim:restoremodules', '\\luabytecodecall'..saved_tables_bytecode)
+
+local function dump_saved_tables()
+ M.msg('pre_dump: save modules and tables to format file')
+ -- save modules
+ for i,name in ipairs (modules) do
+ if not modules[name] then
+ M.msg('saving module '..name)
+ -- reserve (if necessary) a bytecode register
+ modules[name] = M.new_luabytecode ('module '..name)
+ -- store the file into the format file
+ lua.bytecode[modules[name]] = loadfile(kpse.find_file(name,'lua'))
+ end
+ end
+ -- save tables (and restore modules)
+ local saved_tables = [[
+
+ -- include all saved tables in this bytecode register
+ local t = ]]..M.table_to_text(tables)..[[
+
+ -- and make them available via require()
+ package.loaded['minim-saved-tables'] = t
+
+ -- restore all remembered modules from their saved bytecode
+ local s = t['minim:modules']
+ for _, name in ipairs (s) do
+ texio.write_nl('log', 'minim: restoring module '..name)
+ package.loaded[name] = lua.bytecode[ s[name] ] ()
+ end
+
+ ]]
+ lua.bytecode[saved_tables_bytecode] = load(saved_tables)
+end
+
+callback.register ('pre_dump', dump_saved_tables)
+
+--
+
+return M
+
diff --git a/macros/luatex/generic/minim/minim-alloc.tex b/macros/luatex/generic/minim/minim-alloc.tex
new file mode 100644
index 0000000000..66f08c9045
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-alloc.tex
@@ -0,0 +1,184 @@
+
+\ifdefined \minimloaded
+ \message{(skipped)}
+ \expandafter\endinput\fi
+\chardef\minimloaded=\catcode`\:
+\catcode`\:=11
+
+% 1 settings
+
+\suppressoutererror = 1
+\frenchspacing
+
+% 1 programming macros
+
+\newbox\voidbox \setbox0=\box\voidbox
+
+\long\def\ignore#1{}
+\long\def\unbrace#1{#1}
+\long\def\firstoftwo#1#2{#1}
+\long\def\secondoftwo#1#2{#2}
+
+% \spacechar is equivalent to a space character
+{\let\@\relax \global\futurelet\spacechar\@ \relax}
+
+% \nextif c {yes} {no}
+\protected\def\nextif{\nextif:\if}
+% \nextifx c {yes} {no}
+\protected\def\nextifx{\nextif:\ifx}
+% \nextifcat c {yes} {no}
+\protected\def\nextifcat{\nextif:\ifcat}
+
+\long\def\nextif:#1#2#3#4{\begingroup % \if c {yes} {no}
+ \def\nextif:test{#1\nextif:token#2\relax
+ \expandafter\firstoftwo\else
+ \expandafter\secondoftwo\fi
+ {\endgroup#3}{\endgroup#4}}%
+ \futurelet\nextif:token\nextif:test}
+
+% \withoptions [default] {code}
+\protected\def\withoptions[#1]#2{\nextifx[{#2}{#2[#1]}} %]
+
+% \splitcommalist {code} {list}
+\def\splitcommalist#1#2{\splitcommalist:parse{#1}#2,\splitcommalist:end,}
+\def\splitcommalist:parse#1#2,{% command partial-list,
+ \ifx\splitcommalist:end#2\empty\else % test for end-of-list
+ \expandafter\splitcommalist:item
+ \expandafter{\scantextokens{#2}}{#1}\fi} % remove spaces
+\def\splitcommalist:item#1#2\fi{\fi
+ \ifx\splitcommalist:end#1\splitcommalist:end\else#2{#1}\fi
+ \splitcommalist:parse{#2}}
+\protected\def\splitcommalist:end{\splitcommalist:end}
+
+% \decompressedpdf
+\def\decompressedpdf{%
+ \pdfvariable compresslevel = 0
+ \pdfvariable objcompresslevel = 0
+ \pdfvariable recompress = 1
+}
+
+% \unset
+\newcount\unset \unset = -"7FFFFFFF
+
+% 1 ltluatex compatibility
+
+% repair ltluatex, which, without apparent reason, resets all allocation
+% counters, even if they already exist
+\def\minim:ltltx:file{ltluatex.tex}
+\let\ProvidesFile:saved=\ProvidesFile
+\def\ProvidesFile#1#2[#3]{%
+ \ifdefined\ProvidesFile:saved \ProvidesFile:saved{#1}#2[#3]\fi
+ \def\minim:ltltx:arg{#1}%
+ \ifx\minim:ltltx:file\minim:ltltx:arg
+ \let\ProvidesFile=\ProvidesFile:saved
+ \let\endinput:saved=\endinput
+ \protected\edef\endinput{%
+ \minim:ltltx:fix{e@alloc@attribute@count}%
+ \minim:ltltx:fix{e@alloc@whatsit@count}%
+ \minim:ltltx:fix{e@alloc@bytecode@count}%
+ \minim:ltltx:fix{e@alloc@luafunction@count}%
+ \minim:ltltx:fix{e@alloc@luachunk@count}%
+ \minim:ltltx:fix{e@alloc@ccodetable@count}%
+ % also patch in remembering allocations to lua
+ \alloc:patch \noexpand\attribute
+ \alloc:patch \noexpand\whatsit
+ \alloc:patch \noexpand\luabytecode
+ \alloc:patch \noexpand\luachunkname
+ \alloc:patch \noexpand\catcodetable
+ \alloc:patch \noexpand\userrule
+ % restore register allocation functions
+ \directlua{ local C = require('minim-callbacks')
+ callback.register, callback.find, callback.list
+ = C.register, C.find, C.list }%
+ \let\noexpand\endinput=\noexpand\endinput:saved
+ \noexpand\endinput}\fi}
+\def\minim:ltltx:fix#1{%
+ \ifnum0<\the\csname#1\endcsname
+ \wlog{Restoring \csname#1\endcsname to previous value \the\csname#1\endcsname}%
+ \expandafter\noexpand\csname#1\endcsname =\the\csname#1\endcsname\relax\fi}
+\protected\def\alloc:patch#1{%
+ \expandafter\expandafter\expandafter\let
+ \expandafter\expandafter\csname\csstring#1:ltluatex:new\endcsname
+ \csname new\csstring#1\endcsname
+ \expandafter\edef\csname new\csstring#1\endcsname##1{%
+ \noexpand\minim:rememberalloc{\csstring#1}{\noexpand\csstring##1}%
+ \expandafter\noexpand\csname\csstring#1:ltluatex:new\endcsname{##1}}}
+
+% 1 allocation
+
+% use global allocation (see etex.src)
+\let\newcount = \globcount
+\let\newdimen = \globdimen
+\let\newskip = \globskip
+\let\newmuskip = \globmuskip
+\let\newbox = \globbox
+\let\newtoks = \globtoks
+\let\newmarks = \globmarks
+
+% new allocation macros
+
+\def\alloc:makenew#1#2#3{%
+ \unless\ifcsname#3\endcsname
+ \expandafter\newcount \csname#3\endcsname
+ \csname#3\endcsname 0\fi
+ \ifcsname new\csstring#1\endcsname
+ \alloc:patch#1\else
+ \expandafter\edef\csname new\csstring#1\endcsname{%
+ \noexpand\minim:alloc\noexpand#1\noexpand#2%
+ \expandafter\noexpand\csname#3\endcsname}\fi}
+
+\def\minim:alloc#1#2#3#4{% \register \chardef \alloccount \name
+ \global\advance#31%
+ \allocationnumber#3%
+ \global#2#4\allocationnumber
+ \wlog{\string#4=\string#1\the\allocationnumber}%
+ % minim:rememberalloc will be defined from lua side
+ \minim:rememberalloc{\csstring#1}{\csstring#4}}
+
+% all names and counters below are identical to those from ltluatex
+% note: we cannot use \newluafunction, or ltluatex will not load
+\alloc:makenew \function \chardef {e@alloc@luafunction@count}
+\alloc:makenew \attribute \attributedef {e@alloc@attribute@count}
+\alloc:makenew \whatsit \chardef {e@alloc@whatsit@count}
+\alloc:makenew \luabytecode \chardef {e@alloc@bytecode@count}
+\alloc:makenew \luachunkname \chardef:chunk {e@alloc@luachunk@count}
+\alloc:makenew \catcodetable \catcode:chardef {e@alloc@ccodetable@count}
+\alloc:makenew \userrule \chardef {e@alloc@rule@count}
+
+% initialise new catcode tables
+\def\catcode:chardef#1#2{\chardef#1#2\initcatcodetable#2}
+\csname e@alloc@ccodetable@count\endcsname = 4 % because ltluatex allocates 4...
+
+% set initial chunk name value
+\def\chardef:chunk#1#2{\chardef#1#2\directlua{lua.name[\the#2]='\csstring#1'}}
+
+% \setluachunkname
+\protected\def\setluachunkname#1#2{\newluachunkname#1%
+ \directlua{lua.name[\the#1]='\luaescapestring{#2}'}}
+
+% patch in remembering box allocations
+\def\minim:boxchardef#1{%
+ \minim:rememberalloc{box}{\csstring#1}%
+ \mathchardef#1}
+\edef\newbox{%
+ \expandafter\noexpand\csname et@xglob\endcsname
+ 4\box\noexpand\minim:boxchardef}
+
+% undefine our helper functions
+\let\alloc:makenew=\undefined
+
+% 1 format file compatibility
+
+% all other work is done at the lua end
+\directlua { require ('minim-alloc') }
+\directlua { require ('minim-callbacks') }
+
+% restore lua modules (the macro will be defined from the lua end)
+\toksapp\everyjob{\minim:restoremodules
+ \message{... all done.}}
+
+% 
+
+\catcode`\:=\minimloaded
+\endinput
+
diff --git a/macros/luatex/generic/minim/minim-callbacks.lua b/macros/luatex/generic/minim/minim-callbacks.lua
new file mode 100644
index 0000000000..3ac075dc01
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-callbacks.lua
@@ -0,0 +1,265 @@
+
+local M = {}
+
+local function log(msg, ...)
+ texio.write_nl('log', string.format(msg, ...))
+end
+
+-- 1 capturing the callback mechanism
+
+-- if ltluatex is loaded, we must get callback.register back
+if luatexbase ~= nil then
+ local luatex_base = luatexbase
+ luatexbase.uninstall ()
+ luatexbase = luatex_base
+end
+
+local primitives = { }
+M.primitives = primitives
+primitives.register = callback.register
+primitives.find = callback.find
+primitives.list = callback.list
+
+local own_callbacks = {}
+local callback_lists = {}
+local callback_stacks = {}
+
+-- 1 finding callbacks
+
+function M.find (name)
+ local f = own_callbacks[name]
+ if f == nil then
+ return primitives.find(name)
+ else
+ return f
+ end
+end
+
+function M.list (name)
+ local t = {}
+ for n,f in pairs(callback_lists) do
+ if f then
+ t[n] = #f
+ else
+ t[n] = false
+ end
+ end
+ for n,f in pairs(own_callbacks) do
+ if f then
+ t[n] = t[n] or true
+ else
+ t[n] = t[n] or false
+ end
+ end
+ for n,f in pairs(primitives.list()) do
+ if f then
+ t[n] = t[n] or true
+ else
+ t[n] = t[n] or false
+ end
+ end
+ return t
+end
+
+-- 1 registering callbacks
+
+local function register_simple (cb,f)
+ -- prefer user-defined callbacks over built-in
+ local x = own_callbacks[cb]
+ if x == nil then
+ return primitives.register (cb, f)
+ else
+ -- default to false because nil would delete the callback itself
+ own_callbacks[cb] = f or false
+ return -1
+ end
+end
+
+-- will be redefined later
+local function announce_callback(cb, f) end
+
+function M.register (cb, f)
+ announce_callback(cb, f)
+ local list = callback_lists[cb]
+ local stack = callback_stacks[cb]
+ if stack then
+ if f == nil then -- pop
+ local p = stack[#stack]
+ stack[#stack] = nil
+ return register_simple (cb,p)
+ else -- push
+ stack[#stack+1] = M.find (cb)
+ return register_simple (cb,f)
+ end
+ elseif list ~= nil then
+ list[#list+1] = f
+ return -2
+ else
+ return register_simple (cb,f)
+ end
+end
+
+
+-- 1 lists of callback functions
+
+local function call_list_node (lst)
+ return function (head, ...)
+ local list = callback_lists[lst]
+ for _,f in ipairs(list) do
+ local newhead = f(head,...)
+ if node.is_node(newhead) then
+ head = newhead
+ elseif newhead == false then
+ return false
+ end
+ end
+ return head
+ end
+end
+
+local function call_list_data (lst)
+ return function (str)
+ local list = callback_lists[lst]
+ for _,f in ipairs(list) do
+ str = f(str) or str
+ end
+ return str
+ end
+end
+
+local function call_list_simple (lst)
+ return function (...)
+ local list = callback_lists[lst]
+ for _,f in ipairs(list) do
+ f(...)
+ end
+ end
+end
+
+-- 1 creating and calling callbacks
+
+local function register_list (lst, fn)
+ M.register (lst, fn(lst))
+ callback_lists[lst] = {}
+end
+
+local function stack_callback (cb)
+ callback_stacks[cb] = {}
+end
+
+function M.new_callback (name, prop)
+ own_callbacks[name] = false -- false means empty here
+ if prop == 'stack' then
+ stack_callback (name)
+ elseif prop == 'node' then
+ register_list (name, call_list_node)
+ elseif prop == 'simple' then
+ register_list (name, call_list_simple)
+ elseif prop == 'data' then
+ register_list (name, call_list_data)
+ end
+end
+
+function M.call_callback (name, ...)
+ local f = own_callbacks[name]
+ if f then
+ return f (...)
+ else
+ return false
+ end
+end
+
+-- 1 initialisation
+
+-- save all registered callbacks
+local saved = {}
+for n,s in pairs(primitives.list()) do
+ if s then
+ log('save callback: %s', n)
+ saved[n] = callback.find(n)
+ end
+end
+
+-- replace the primitive registering
+callback.register = M.register
+callback.find = M.find
+callback.list = M.list
+
+-- string processing callbacks
+register_list ('process_input_buffer', call_list_data)
+register_list ('process_output_buffer', call_list_data)
+register_list ('process_jobname', call_list_data)
+
+-- node list processing callbacks
+register_list ('pre_linebreak_filter', call_list_node)
+register_list ('post_linebreak_filter', call_list_node)
+--register_list ('append_to_vlist_filter', call_list_node) -- TODO this breaks something
+register_list ('hpack_filter', call_list_node)
+register_list ('vpack_filter', call_list_node)
+register_list ('pre_output_filter', call_list_node)
+
+-- mlist_to_mlist and mlist_to_mlist
+M.new_callback ('mlist_to_mlist', 'node')
+M.new_callback ('mlist_to_hlist', 'stack')
+M.register ('mlist_to_hlist', node.mlist_to_hlist )
+primitives.register ('mlist_to_hlist', function (head, ...)
+ local newhead = M.call_callback ('mlist_to_mlist', head, ...)
+ if newhead ~= true then
+ head = newhead or head
+ end
+ newhead = M.call_callback ('mlist_to_hlist', head, ...)
+ return newhead
+end)
+
+-- simple listable callbacks
+register_list ('contribute_filter', call_list_simple)
+register_list ('pre_dump', call_list_simple)
+register_list ('wrapup_run', call_list_simple)
+register_list ('finish_pdffile', call_list_simple)
+register_list ('finish_pdfpage', call_list_simple)
+register_list ('insert_local_par', call_list_simple)
+
+register_list ('ligaturing', call_list_simple)
+register_list ('kerning', call_list_simple)
+
+-- stack callbacks
+stack_callback ('hpack_quality')
+stack_callback ('vpack_quality')
+stack_callback ('hyphenate')
+stack_callback ('linebreak_filter')
+stack_callback ('buildpage_filter')
+stack_callback ('build_page_insert')
+
+-- process_rule
+M.new_callback ('process_rule', 'simple')
+primitives.register ('process_rule', function (rule, ...)
+ local p = own_callbacks[rule.index]
+ if p then
+ p (rule, ...)
+ else
+ M.call_callback ('process_rule')
+ end
+end)
+
+-- restore all registered callbacks
+for n,f in pairs(saved) do
+ log('restore callback: %s', n)
+ M.register (n,f)
+end
+saved = nil
+
+
+local function announce_callback(cb, f)
+ if f then
+ log('callback added: %s', cb)
+ else
+ log('callback removed: %s', cb)
+ end
+end
+
+
+--
+
+return M
+
+
diff --git a/macros/luatex/generic/minim/minim-doc.sty b/macros/luatex/generic/minim/minim-doc.sty
new file mode 100644
index 0000000000..1d3c2d4cea
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-doc.sty
@@ -0,0 +1,215 @@
+
+%% This is the style file for the manuals of the minim format and related
+%% packages.
+
+\ifdefined \manual
+ \expandafter\endinput\fi
+
+\input minim
+
+\pdfalevel 3a
+\overfullrule = 0pt
+
+% 1 page layout
+
+\pdfvariable horigin 0pt
+\pdfvariable vorigin 0pt
+\frenchspacing
+\raggedbottom
+
+\uselanguage{ukenglish}
+\hyphenation {
+ mark-tab-le-cell
+ }
+
+\parindent 0pt
+\baselineskip 12pt plus 1pt
+\parskip 8pt plus 4pt minus 1pt
+
+\abovedisplayskip 3pt plus 2pt
+\belowdisplayskip 4pt plus 2pt
+
+\hsize 12cm
+\vsize 56\baselineskip
+
+\voffset = \dimexpr (\pageheight-\vsize)/2\relax
+\hoffset = \dimexpr (\pagewidth-\hsize)/2\relax
+
+% 1 fonts
+
+\input luaotfload.sty
+\font\tenrm {Latin Modern Roman:script=latn;protrusion=default} at 10pt
+\font\tenbf {Latin Modern Roman/B:script=latn} at 10pt
+\font\tenit {Latin Modern Roman/I:script=latn} at 10pt
+\font\tentt {Latin Modern Mono:script=latn;+smcp} at 10pt
+\font\title {Latin Modern Roman/B:script=latn} at 12pt
+\font\Title {Latin Modern Roman/B:script=latn} at 16pt
+
+\font\tenmath {Latin Modern Math:mode=base;script=math;ssty=0} at 10pt
+\font\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1} at 7pt
+\font\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2} at 5pt
+\textfont 0 = \tenmath
+\scriptfont 0 = \tenmaths
+\scriptscriptfont 0 = \tenmathss
+
+\font\altmath {Tex Gyre Pagella Math:mode=base;script=math;ssty=0} at 10pt
+\font\altmaths {Tex Gyre Pagella Math:mode=base;script=math;ssty=1} at 7pt
+\font\altmathss {Tex Gyre Pagella Math:mode=base;script=math;ssty=2} at 5pt
+\textfont 1 = \altmath
+\scriptfont 1 = \altmaths
+\scriptscriptfont 1 = \altmathss
+
+\expandglyphsinfont \tenrm 40 25 5
+\protrudechars=2 \adjustspacing=2
+\tenrm
+
+\mathfam{blackboard, `\mscra-`\mscrz} 1
+
+% 1 code typesetting
+
+\def\red#1{\quitvmode\pdfextension
+ literal{0.75 0 0 rg}{#1}\pdfextension literal{0 g}}
+
+\def\emph#1{{\tenit #1\/}}
+
+\def\breakablespace{\penalty0~}
+\catcode`\⟦=\active
+\def⟦{\quitvmode\begingroup\catcode`\∥=0\relax
+ \markparagraphsfalse
+ \def\do##1{\catcode`##1=12}\dospecials
+ \catcode`\ =\active
+ \letcharcode`\ =\breakablespace\obeylines
+ \parskip0pt\tentt
+ \nextif*{\verbatim\ignore}{\expandafter\ignore\verbatim}}
+\def\verbatim#1⟧{\red{\markelement{Code}{#1}}\endgroup}
+
+% 1 the minim symbol
+
+\newbox\notehead
+\newmetapostinstance \mnmMP
+\runmetapost \mnmMP {
+beginfig(1)
+ w:=1/27; pickup pencircle scaled 1/9;
+ path c; c :=
+ (-3/5,-1/6 ) {down}..
+ (-1/5,-1/2 ) {right}..
+ ( 3/5, 1/6 ) {up}..
+ ( 1/5, 1/2 ) {left}.. cycle;
+ filldraw c withcolor .75 red;
+ path p; p :=
+ (-0.383-w,-0.323-w) ..tension 1.35.. (-0.094-w, 0.094+w) ..tension 1.5..
+ ( 0.383+w, 0.323+w) ..tension 1.35.. ( 0.094+w,-0.094-w) ..tension 1.5.. cycle ;
+ p := (-1,-1) -- (1,-1) -- (1,1) -- p -- (1,1) -- (-1,1) -- cycle ;
+ clip currentpicture to p;
+ draw (3/5, 1/6) -- (3/5, 5/2) withcolor .75 red;
+ setbounds currentpicture to c;
+ currentpicture := currentpicture scaled 8pt ;
+endfig;}
+\boxnextmpimage \mnmMP \notehead
+\setbox\notehead=\hbox{\markartifact{Layout}{\box\notehead}}
+\closemetapostinstance \mnmMP
+
+%
+% 1 document structure
+
+% page artifacts
+\edef\tmp{\markartifact{Pagination /Subtype/Footer}{\the\footline}}
+\footline\expandafter{\tmp}
+\def\footnoterule{\markartifact{Layout}{\kern-3\p@
+ \hrule width 2truein \kern 2.6\p@}} % the \hrule is .4pt high
+
+% \startlist \item x. ... \stoplist
+\def\listskip{\vskip 3pt plus 2pt\vskip-\parskip}
+\def\startlist{\smallskip\startelement{L}}
+\def\stoplist{\stopelement{L}\smallskip}
+\def\item#1.{\listskip
+ \nextpartag{LI}\hangindent2em\quitvmode
+ \hbox to 2em{\hss\startelement{Lbl}#1.~~}%
+ \startelement{LBody}\ignorespaces}
+
+% \chapter Title \par
+\addstructuretype Sect Chapter
+\protected\def\chapter#1 \par{%
+ \vfil\break
+ \ensurestopelement{Section}%
+ \startelement{Chapter}%
+ \outline open {#1}%
+ \nextpartag{H}\red{\Title#1\hfill\copy\notehead}%
+ \addtotoc{\chapter{#1}{\lastdestinationname}}%
+ \bigskip}
+
+% \section Title \par
+\addstructuretype Sect Section
+\protected\def\section#1 \par{%
+ \bigskip\penalty-50\relax
+ \startelement{Section}%
+ \outline closed {#1}%
+ \nextpartag{H}\quitvmode
+ \addtotoc{\section{#1}{\lastdestinationname}}%
+ \red{\title#1}%
+ \par\nobreak}
+
+% table of contents
+\newtoks\toc \newif\iftoc \toctrue
+\def\addtotoc#1{%
+ \iftoc \edef\toctmp{#1}%
+ \write\auxfile\expandafter
+ {\expandafter\toksapp\expandafter\toc
+ \expandafter{\toctmp{\the\count0}}}\fi\toctrue}
+
+% an auxiliary file
+\newread \auxfile
+\immediate\openin\auxfile = \jobname.aux
+\ifeof\auxfile
+ \def\next{}\else
+ \def\next{\input \jobname.aux}\fi
+\immediate\closein\auxfile \next
+\newwrite \auxfile
+\immediate\openout\auxfile = \jobname.aux
+
+\autotagformulas
+
+\def\maketitle{%
+ \setembeddedfilesmoddate {\getmetadata date}
+ \begingroup
+ \def\outline##1##{\ignore}
+ \tocfalse \chapter \getmetadata title
+ \hfill \tenrm version \getmetadata version
+ \par\endgroup
+ \marktableaslist \halign {\strut
+ \qquad##\quad&##\hfil\cr
+ author&\getmetadata author\cr
+ contact&{\def\tmp{@}\def\TMP{.}%
+ minim\tmp elrenkema\TMP nl}\cr}
+ \smallskip}
+
+% 1 Chapters and full manuals
+
+\def\licencesection{\section Licence
+
+\embedfile global file {EUPL-1.2-EN.txt}
+ desc {Licence for this package (EUPL).}
+ name LICENCE mimetype text/plain
+ relation Unspecified uncompressed
+
+This package may be distributed under the terms of the European Union Public
+Licence (EUPL) version 1.2 or later. An english version of this licence has
+been included as an attachment to this file; copies in other languages can be
+obtained at
+\stopformulatagging$$\hbox
+{\hyperlink url {https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12}%
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\endlink}$$\startformulatagging}
+
+
+% for identifying which file we are typesetting
+\edef\thejobname{\expandafter\scantextokens\expandafter{\jobname}}
+\newif \ifchapter
+\def\manual#1{\def\tmp{#1}\ifx\thejobname\tmp
+ \chapterfalse\else\chaptertrue\fi}
+\def\endmanual{\ifchapter\expandafter\endinput\else
+ \licencesection\expandafter\bye\fi}
+
+%  introduction
+
+\endinput
+
diff --git a/macros/luatex/generic/minim/minim-etex.tex b/macros/luatex/generic/minim/minim-etex.tex
new file mode 100644
index 0000000000..bdf71def16
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-etex.tex
@@ -0,0 +1,413 @@
+
+% This is a stripped-down version of etex.src, meant as companion to
+% minim-plain.tex.
+%
+% It follows e-TeX V2.1;0-luatex2.
+%
+% The following has been removed:
+% - Module loading
+% - Version checks
+%
+% The following has been retained:
+% - Language handling (somewhat simplified)
+% - Tracing and logging extensions
+% - The \eTeX symbol
+% - Register allocation
+
+\catcode `\@=\catcode `\A
+
+% Define the language-handling commands
+
+\def \uselanguage #1%
+ {\ifcsname lang@#1\endcsname
+ \language=\csname lang@#1\endcsname
+ \lefthyphenmin=\csname lhm@#1\endcsname
+ \righthyphenmin=\csname rhm@#1\endcsname
+ \ifcsname lu@texhyphen@loaded@\the\language\endcsname \else
+ \global\expandafter\def\csname
+ lu@texhyphen@loaded@\the\language\endcsname{}%
+ \directlua{
+ if not status.ini_version then
+ require("luatex-hyphen")
+ luatexhyphen.loadlanguage("\luatexluaescapestring{#1}",
+ \the\language)
+ end}%
+ \fi
+ \ifdefined\uselanguage@hook \uselanguage@hook{#1}\fi
+ \else
+ \begingroup\errorcontextlines=0\relax
+ \errhelp {You are trying to use a language which has not previously
+ been defined; remember that any language you want to use
+ will need to have been specified at the time the format
+ was created.%
+ }%
+ \errmessage {Language #1 undefined.}\endgroup
+ \fi}
+
+\def \addlanguage #1#2#3#4#5{% language patterns exceptions lhm rhm
+ \expandafter\newlanguage \csname lang@#1\endcsname
+ \expandafter\chardef \csname lhm@#1\endcsname=#4
+ \expandafter\chardef \csname rhm@#1\endcsname=#5
+ \csname if\directlua{% do we want to skip this language now?
+ require("luatex-hyphen")
+ if (luatexhyphen.lookupname("\luatexluaescapestring{#1}") == nil)
+ or (\number\csname lang@#1\endcsname == 0) then
+ tex.sprint("false") % no, load it (execute 'else' part)
+ else
+ tex.sprint("true") % yes, skip
+ end}\endcsname
+ \else
+ \uselanguage {#1}%
+ \input #2
+ \if *#3*\else \input #3 \fi
+ \edef \fmtversion {\fmtversion/#1}%
+ \fi
+ \ifdefined\addlanguage@hook \addlanguage@hook{#1}\fi}
+
+% Decrement \count 19, because \newlanguage will increment it again
+
+\advance \count 19 by -1
+
+% We are about to try to process a user/site-specific file "language.def",
+% which establishes a Babel-like language selection environment.
+
+\input language.def
+
+% All that was just to set up natural language handling...
+% The "real" work of "etex.src", however, is to augment the non-primitives
+% of Plain.TeX to incorporate e-TeX specific features, and to add new
+% non-primitives to simplify access to new e-TeX specific primitives.
+
+\message {Augmenting the Plain TeX definitions:}
+\message {\string \tracingall;}
+
+\def \tracingall
+ {\tracingonline=\@ne
+ \tracingcommands=\thr@@ % plain.tex has \tw@
+ \tracingstats=\tw@
+ \tracingpages=\@ne
+ \tracingoutput=\@ne
+ \tracinglostchars=\tw@ % plain.tex has \@ne
+ \tracingmacros=\tw@
+ \tracingparagraphs=\@ne
+ \tracingrestores=\@ne
+ \showboxbreadth=\maxdimen
+ \showboxdepth=\maxdimen
+ \errorstopmode
+ \tracinggroups=\@ne
+ \tracingifs=\@ne
+ \tracingscantokens=\@ne
+ \tracingnesting=\@ne
+ \tracingassigns=\tw@
+ }
+
+\message {Adding new e-TeX definitions:}
+
+\message {\string \eTeX,}
+\def \eTeX {$\varepsilon$-\TeX} %%% the simple version, not suitable for maths;
+
+\message {\string \loggingall,}
+\def \loggingall {\tracingall \tracingonline=\z@}
+
+\message {\string \tracingnone,}
+\def \tracingnone
+ {\tracingassigns=\z@
+ \tracingnesting=\z@
+ \tracingscantokens=\z@
+ \tracingifs=\z@
+ \tracinggroups=\z@
+ \showboxdepth=\thr@@
+ \showboxbreadth=5
+ \tracingrestores=\z@
+ \tracingparagraphs=\z@
+ \tracingmacros=\z@
+ \tracinglostchars=\@ne
+ \tracingoutput=\z@
+ \tracingpages=\z@
+ \tracingstats=\z@
+ \tracingcommands=\z@
+ \tracingonline=\z@
+ }
+
+\message {register allocation;}
+
+\newcount \et@xins % our insertion counter (\insc@unt is used differently)
+
+% We have to adjust the Plain TeX register allocation counts for our
+% slightly modified book-keeping:
+
+\advance \count 10 by 1 % \count 10=23 % allocates \count registers 23, 24, ...
+\advance \count 11 by 1 % \count 11=10 % allocates \dimen registers 10, 11, ...
+\advance \count 12 by 1 % \count 12=10 % allocates \skip registers 10, 11, ...
+\advance \count 13 by 1 % \count 13=10 % allocates \muskip registers 10, 11, ...
+\advance \count 14 by 1 % \count 14=10 % allocates \box registers 10, 11, ...
+\advance \count 15 by 1 % \count 15=10 % allocates \toks registers 10, 11, ...
+\advance \count 16 by 1 % \count 16=0 % allocates input streams 0, 1, ...
+\advance \count 17 by 1 % \count 17=0 % allocates output streams 0, 1, ...
+\advance \count 18 by 1 % \count 18=4 % allocates math families 4, 5, ...
+\advance \count 19 by 1 % \count 19=0 % allocates \language codes 0, 1, ...
+
+\et@xins=\insc@unt % \et@xins=255 % allocates insertions 254, 253, ...
+
+% We don't change the Plain TeX definitions of \newcount, etc., but the
+% \alloc@ macro doing the actual work is redefined.
+
+% When the normal register pool for \count, \dimen, \skip, \muskip,
+% \box, or \toks registers is exhausted, we switch to the extended pool.
+
+\def \alloc@ #1#2#3#4#5%
+ {\ifnum \count 1#1 < #4% make sure there's still room
+ \allocationnumber=\count 1#1
+ \global \advance \count 1#1 by \@ne
+ \global #3#5=\allocationnumber
+ \wlog {\string #5=\string #2\the \allocationnumber}%
+ \else \ifnum #1 < 6
+ \begingroup \escapechar=\m@ne
+ \expandafter \alloc@@ \expandafter {\string #2}#5%
+ \else
+ \errmessage {No room for a new #2}%
+ \fi
+ \fi
+ }
+
+% The \expandafter construction used here allows the generation of
+% \newcount and \globcount from #1=count. Moreover (and more important)
+% this construction avoids the appearance of \outer macros inside
+% macro definitions or conditionals.
+
+\def \alloc@@ #1#2%
+ {\endgroup % restore \escapechar
+ \message {Normal \csname#1\endcsname register pool exhausted,
+ switching to extended pool.}%
+ \global \expandafter
+ \let \csname new#1\expandafter \endcsname \csname glob#1\endcsname
+ \csname new#1\endcsname#2%
+ }
+
+% We do change the Plain TeX definition of \newinsert
+
+\outer \def \newinsert #1%make sure there's still room for ...
+ {\ch@ck 0 \et@xins \count % ... a \count, ...
+ {\ch@ck 1 \et@xins \dimen % ... \dimen, ...
+ {\ch@ck 2 \et@xins \skip % ... \skip, ...
+ {\ch@ck 4 \et@xins \box % ... and \box register
+ {\global \advance \et@xins by \m@ne
+ \unless
+ \ifnum \insc@unt < \et@xins
+ \global \insc@unt=\et@xins
+ \fi
+ \allocationnumber=\et@xins
+ \global \chardef #1=\allocationnumber
+ \wlog {\string #1=\string \insert \the \allocationnumber}%
+ }%
+ }%
+ }%
+ }%
+ }
+
+\def \ch@ck #1#2#3#4%
+ {\ifnum \count 1#1 < #2#4\else \errmessage {No room for a new #3}\fi}
+
+% And we define \reserveinserts, so that you can say \reserveinserts{17}
+% in order to reserve room for up to 17 additional insertion classes that will
+% not be taken away by \newcount, \newdimen, \newskip, or \newbox.
+
+\outer \def \reserveinserts#1%
+ {\global \insc@unt=\numexpr \et@xins \ifnum #1 > \z@ -#1\fi \relax}
+
+\message {extended register allocation;}
+
+% Now, we define \globcount, \globbox, etc., so that you can say
+% \globcount\foo and \foo will be defined (with \countdef) to be the
+% next count register from the vastly larger but somewhat less efficient
+% extended register pool. We also define \loccount, etc., but these
+% register definitions are local to the current group.
+
+\count 260=277 % globally allocates \count registers 277, 278, ...
+\count 261=\@cclvi % globally allocates \dimen registers 256, 257, ...
+\count 262=\@cclvi % globally allocates \skip registers 256, 257, ...
+\count 263=\@cclvi % globally allocates \muskip registers 256, 257, ...
+\count 264=\@cclvi % globally allocates \box registers 256, 257, ...
+\count 265=\@cclvi % globally allocates \toks registers 256, 257, ...
+\count 266=\@ne % globally allocates \marks classes 1, 2, ...
+
+\def \et@xmaxregs {32768}
+
+\count 270=\et@xmaxregs % locally allocates \count registers 32767, 32766, ...
+\count 271=\et@xmaxregs % ditto for \dimen registers
+\count 272=\et@xmaxregs % ditto for \skip registers
+\count 273=\et@xmaxregs % ditto for \muskip registers
+\count 274=\et@xmaxregs % ditto for \box registers
+\count 275=\et@xmaxregs % ditto for \toks registers
+\count 276=\et@xmaxregs % ditto for \marks classes
+
+% \count registers 256-259 and 267-269 are not (yet) used
+
+\outer \def \globcount {\et@xglob 0 \count \countdef}
+ \def \loccount {\et@xloc 0 \count \countdef}
+\outer \def \globdimen {\et@xglob 1 \dimen \dimendef}
+ \def \locdimen {\et@xloc 1 \dimen \dimendef}
+\outer \def \globskip {\et@xglob 2 \skip \skipdef}
+ \def \locskip {\et@xloc 2 \skip \skipdef}
+\outer \def \globmuskip {\et@xglob 3 \muskip \muskipdef}
+ \def \locmuskip {\et@xloc 3 \muskip \muskipdef}
+\outer \def \globbox {\et@xglob 4 \box \mathchardef}
+ \def \locbox {\et@xloc 4 \box \mathchardef}
+\outer \def \globtoks {\et@xglob 5 \toks \toksdef}
+ \def \loctoks {\et@xloc 5 \toks \toksdef}
+\outer \def \globmarks {\et@xglob 6 \marks \mathchardef}
+ \def \locmarks {\et@xloc 6 \marks \mathchardef}
+
+\let\newmark=\globmarks %%% 2.0;14
+\let\newmarks=\globmarks
+
+\def \et@xglob #1#2#3#4%
+ {\et@xchk #1#2% make sure there's still room
+ {\allocationnumber=\count 26#1
+ \global \advance \count 26#1 by \@ne
+ \global #3#4=\allocationnumber
+ \wlog {\string #4=\string #2\the \allocationnumber}%
+ }%
+ }
+
+\def \et@xloc#1#2#3#4%
+ {\et@xchk #1#2% make sure there's still room
+ {\advance \count 27#1 by \m@ne
+ \allocationnumber=\count 27#1
+ #3#4=\allocationnumber
+ \wlog {\string #4=\string #2\the \allocationnumber \space (local)}%
+ }%
+ }
+
+\def \et@xchk #1#2#3%
+ {\ifnum \count 26#1 < \count 27#1
+ #3%
+ \else
+ \errmessage {No room for a new #2}%
+ \fi
+ }
+
+% Next we define \globcountblk, \loccountblk, etc., so that one can
+% write \globcountblk\foo{17} and \foo will be defined (with \mathchardef)
+% as the first (the zeroth?) of a block of 17 consecutive registers.
+% Thus the user is intended to reference elements <\foo+0> to <\foo+n-1>,
+% where n is the length of the block allocated.
+
+\outer \def \globcountblk {\et@xgblk 0 \count}
+ \def \loccountblk {\et@xlblk 0 \count}
+\outer \def \globdimenblk {\et@xgblk 1 \dimen}
+ \def \locdimenblk {\et@xlblk 1 \dimen}
+\outer \def \globskipblk {\et@xgblk 2 \skip}
+ \def \locskipblk {\et@xlblk 2 \skip}
+\outer \def \globmuskipblk {\et@xgblk 3 \muskip}
+ \def \locmuskipblk {\et@xlblk 3 \muskip}
+\outer \def \globboxblk {\et@xgblk 4 \box}
+ \def \locboxblk {\et@xlblk 4 \box}
+\outer \def \globtoksblk {\et@xgblk 5 \toks}
+ \def \loctoksblk {\et@xlblk 5 \toks}
+\outer \def \globmarksblk {\et@xgblk 6 \marks}
+ \def \locmarksblk {\et@xlblk 6 \marks}
+
+% And, both to provide a higher-level interface to the block allocation
+% scheme, and to demonstrate possible applications of the new \...expr
+% primitives, we also define \globcountvector and \loccountvector (etc)
+% which allow the user to access elements with embedded arithmetic, as in
+
+% \globcountvector \foo {12}
+% \foo {\count 0 + 3} = \foo {\count 1 * 2}
+
+\outer \def \globcountvector {\et@xgvec 0 \count}
+ \def \loccountvector {\et@xlvec 0 \count}
+\outer \def \globdimenvector {\et@xgvec 1 \dimen}
+ \def \locdimenvector {\et@xlvec 1 \dimen}
+\outer \def \globskipvector {\et@xgvec 2 \skip}
+ \def \locskipvector {\et@xlvec 2 \skip}
+\outer \def \globmuskipvector {\et@xgvec 3 \muskip}
+ \def \locmuskipvector {\et@xlvec 3 \muskip}
+\outer \def \globboxvector {\et@xgvec 4 \box}
+ \def \locboxvector {\et@xlvec 4 \box}
+\outer \def \globtoksvector {\et@xgvec 5 \toks}
+ \def \loctoksvector {\et@xlvec 5 \toks}
+\outer \def \globmarksvector {\et@xgvec 6 \marks}
+ \def \locmarksvector {\et@xlvec 6 \marks}
+
+\def \et@xgblk #1#2#3#4%
+ {\et@xchkblk #1#2{#4}% make sure there's still room
+ {\allocationnumber=\count 26#1
+ \global \advance \count 26#1 by #4%
+ \global \mathchardef #3=\allocationnumber
+ \wlog {\string #3=\string #2blk{\number #4} at \the \allocationnumber}%
+ }%
+ }
+
+\def \et@xlblk #1#2#3#4%
+ {\et@xchkblk #1#2{#4}% make sure there's still room
+ {\advance \count 27#1 by -#4%
+ \allocationnumber=\count 27#1
+ \mathchardef #3=\allocationnumber
+ \wlog {\string #3=\string #2blk{\number #4}
+ at \the \allocationnumber \space (local)%
+ }%
+ }%
+ }
+
+\begingroup
+\catcode `\# = 12
+\gdef \et@xhash {#}
+\endgroup
+
+\def \et@xgvec #1#2#3#4%
+ {\et@xchkblk #1#2{#4}% make sure there's still room
+ {\allocationnumber=\count 26#1
+ \global \advance \count 26#1 by #4%
+ \ifx #2\box
+ \def \2{}%
+ \else \ifx #2\marks
+ \def \2{}%
+ \else
+ \def \2{\string #2}%
+ \fi
+ \fi
+ \xdef #3##1{\2 \noexpand \numexpr \the \allocationnumber+##1\relax}%
+ \wlog {\string #3 {\et@xhash 1} =
+ \2 {\the \allocationnumber+\et@xhash 1} (global #2 vector)%
+ }%
+ }%
+ }
+
+\def \et@xlvec #1#2#3#4%
+ {\et@xchkblk #1#2{#4}% make sure there's still room
+ {\advance \count 27#1 by -#4%
+ \allocationnumber=\count27#1
+ \mathchardef #3=\allocationnumber
+ \ifx #2\box
+ \def \2{}%
+ \else \ifx #2\marks
+ \def \2{}%
+ \else
+ \def \2{\string #2}%
+ \fi
+ \fi
+ \edef #3##1{\2 \noexpand \numexpr \the \allocationnumber+##1\relax}%
+ \wlog {\string #3 {\et@xhash 1} =
+ \2 {\the \allocationnumber+\et@xhash 1} (local #2 vector)%
+ }%
+ }%
+ }
+
+\def \et@xchkblk #1#2#3#4%
+ {\ifnum #3 < \z@
+ \errmessage {Negative register block size \number #3}%
+ \else \ifnum \numexpr \count 26#1+#3 > \count 27#1
+ \errmessage {No room for new #2block of size \number#3}%
+ \else
+ #4%
+ \fi
+ \fi
+ }
+
+% And finally re-catcode commercial-at
+
+\catcode `\@=12
+
+
diff --git a/macros/luatex/generic/minim/minim-hooks.lua b/macros/luatex/generic/minim/minim-hooks.lua
new file mode 100644
index 0000000000..c399547c9e
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-hooks.lua
@@ -0,0 +1,30 @@
+
+-- Adds a callback just before a box is shipped out, opposite to
+-- 'finish_pdfpage'.
+
+local alloc = require('minim-alloc')
+local cb = require ('minim-callbacks')
+alloc.remember('minim-hooks')
+
+local M = { }
+
+cb.new_callback('pre_shipout', 'simple')
+
+M.primitive_shipout = tex.shipout
+function tex.shipout(nr)
+ cb.call_callback('pre_shipout', nr)
+ M.primitive_shipout(nr)
+end
+
+local shipout_box = alloc.new_box('minim:shipout:box')
+
+alloc.luadef('minim:shipout', function()
+ tex.box[shipout_box] = token.scan_list()
+ cb.call_callback('pre_shipout', shipout_box)
+ -- we must let tex do the rest, because some other package may have
+ -- redefined \shipout before us.
+ tex.sprint(token.create('minim:shipout:do'))
+end, 'protected')
+
+return M
+
diff --git a/macros/luatex/generic/minim/minim-hooks.tex b/macros/luatex/generic/minim/minim-hooks.tex
new file mode 100644
index 0000000000..b3b8092654
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-hooks.tex
@@ -0,0 +1,56 @@
+
+% The purpose of this module is allowing arbitrary code be run at specific
+% places. I have not yet included it in the manual, because I still am a bit
+% unsure about the details of the implementation.
+%
+% The first thing done here is inserting a callback into \shipout (and
+% tex.shipout) mirroring finish_pdf, allowing last-minute manipulation before
+% the pdf code will be assembled.
+%
+% The second feature is adding things to the beginning of a paragraph without
+% (seemingly) disturbing \everypar, and also adding things to the next
+% paragraph only.
+%
+% Both features are implemented in a way that is repeatable and should coexist
+% peacefully with other packages doing something of the same. But please let me
+% know if you run into any problems.
+
+\ifdefined\minimhooksloaded
+ \message{(skipped)}
+ \expandafter\endinput\fi
+\chardef\minimhooksloaded = \catcode`\:
+\catcode`\: = 11
+
+\input minim-alloc
+
+% 1 the pre_shipout callback
+
+\newbox\minim:shipout:box \let\minim:shipout:orig = \shipout
+\def\minim:shipout:do{\minim:shipout:orig\box\minim:shipout:box}
+\directlua{require('minim-hooks')} \let\shipout\minim:shipout
+
+% 1 invisibly adding to \everypar
+
+\let\minim:everypar = \everypar
+\newtoks\minim:ateverypar
+\newtoks\minim:atnextpar
+\newtoks\everypar \everypar\minim:everypar
+\minim:everypar\expandafter{\expandafter
+ \minim:changeparindent
+ % expansion makes this process repeatable
+ \expandafter\the\everypar
+ \the\minim:ateverypar
+ \minim:atnextpar\expandafter
+ {\expandafter}\the\minim:atnextpar}
+\let\minim:changeparindent = \relax % as of yet unused
+
+% There is no need for the following.
+
+%\let\minim:par = \par
+%\newtoks\minim:aftereverypar
+%\protected\def\par{\ifhmode \unskip
+% \the\minim:aftereverypar \fi \minim:par}
+
+\catcode`\: = \minimhooksloaded
+
+
diff --git a/macros/luatex/generic/minim/minim-lmodern.tex b/macros/luatex/generic/minim/minim-lmodern.tex
new file mode 100644
index 0000000000..61bc0054e9
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-lmodern.tex
@@ -0,0 +1,28 @@
+
+% This file, used in the minim and minim-mp formats, replaces the named fonts
+% from plain.tex with latin modern equivalents.
+
+\ifdefined\minimlmodernloaded
+ \message{(skipped)}
+ \expandafter\endinput\fi
+\chardef\minimlmodernloaded=\catcode`\:
+\catcode`\:=11
+
+\def\preloadfont#1#2#3{\def#1{\initfontloader\font#1{#2}at#3#1}}
+\def\initfontloader{\input luaotfload.sty \let\initfontloader=\relax}
+
+\preloadfont \tenrm {Latin Modern Roman:script=latn;+liga;+kern;+dlig}{10pt}
+\preloadfont \tenit {Latin Modern Roman/I:script=latn;+liga;+kern;+dlig}{10pt}
+\preloadfont \tenbf {Latin Modern Roman/B:script=latn;+liga;+kern;+dlig}{10pt}
+\preloadfont \tensl {Latin Modern Roman Slanted:script=latn;+liga;+kern;+dlig}{10pt}
+\preloadfont \tentt {Latin Modern Mono:script=latn;+liga;+kern;+dlig}{10pt}
+
+\preloadfont\tenmath {Latin Modern Math:mode=base;script=math;ssty=0}{10pt}
+\preloadfont\tenmaths {Latin Modern Math:mode=base;script=math;ssty=1}{7pt}
+\preloadfont\tenmathss {Latin Modern Math:mode=base;script=math;ssty=2}{5pt}
+
+\toksapp\everyjob{\tenmath\tenmaths\tenmathss\tenrm
+ \textfont0=\tenmath\scriptfont0=\tenmaths\scriptscriptfont0=\tenmathss}
+
+\catcode`\:=\minimlmodernloaded
+
diff --git a/macros/luatex/generic/minim/minim-plain.tex b/macros/luatex/generic/minim/minim-plain.tex
new file mode 100644
index 0000000000..85fd802b8b
--- /dev/null
+++ b/macros/luatex/generic/minim/minim-plain.tex
@@ -0,0 +1,786 @@
+
+% This is a stripped-down version of plain TeX.
+%
+% It follows plain.tex version 3.141592653.
+%
+% The following has been removed:
+% - All fonts and font switches
+% - \fmtname and \fmtversion
+% - \mathcode, \delcode, \mathchardef, \mathaccent and \delimiter settings
+% - Most math-related macros
+% - Loading hyphen.tex
+
+\catcode`\{=1 % left brace is begin-group character
+\catcode`\}=2 % right brace is end-group character
+\catcode`\$=3 % dollar sign is math shift
+\catcode`\&=4 % ampersand is alignment tab
+\catcode`\#=6 % hash mark is macro parameter character
+\catcode`\^=7 \catcode`\^^K=7 % circumflex and uparrow are for superscripts
+\catcode`\_=8 \catcode`\^^A=8 % underline and downarrow are for subscripts
+\catcode`\^^I=10 % ascii tab is a blank space
+\chardef\active=13 \catcode`\~=\active % tilde is active
+\catcode`\^^L=\active \outer\def^^L{\par} % ascii form-feed is "\outer\par"
+
+\message{Preloading the plain format: codes,}
+
+% We had to define the \catcodes right away, before the message line,
+% since \message uses the { and } characters.
+% When INITEX (the TeX initializer) starts up,
+% it has defined the following \catcode values:
+% \catcode`\^^@=9 % ascii null is ignored
+% \catcode`\^^M=5 % ascii return is end-line
+% \catcode`\\=0 % backslash is TeX escape character
+% \catcode`\%=14 % percent sign is comment character
+% \catcode`\ =10 % ascii space is blank space
+% \catcode`\^^?=15 % ascii delete is invalid
+% \catcode`\A=11 ... \catcode`\Z=11 % uppercase letters
+% \catcode`\a=11 ... \catcode`\z=11 % lowercase letters
+% all others are type 12 (other)
+
+% Here is a list of the characters that have been specially catcoded:
+\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
+ \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~}
+% (not counting ascii null, tab, linefeed, formfeed, return, delete)
+% Each symbol in the list is preceded by \do, which can be defined
+% if you want to do something to every item in the list.
+
+% We make @ signs act like letters, temporarily, to avoid conflict
+% between user names and internal control sequences of plain format.
+\catcode`@=11
+
+% INITEX sets \uccode`x=`X and \uccode `X=`X for all letters x,
+% and \lccode`x=`x, \lccode`X=`x; all other values are zero.
+% No changes to those tables are needed in plain TeX format.
+
+% INITEX sets \sfcode x=1000 for all x, except that \sfcode`X=999
+% for uppercase letters. The following changes are needed:
+\sfcode`\)=0 \sfcode`\'=0 \sfcode`\]=0
+% The \nonfrenchspacing macro will make further changes to \sfcode values.
+
+% To make the plain macros more efficient in time and space,
+% several constant values are declared here as control sequences.
+% If they were changed, anything could happen; so they are private symbols.
+\chardef\@ne=1
+\chardef\tw@=2
+\chardef\thr@@=3
+\chardef\sixt@@n=16
+\chardef\@cclv=255
+\mathchardef\@cclvi=256
+\mathchardef\@m=1000
+\mathchardef\@M=10000
+\mathchardef\@MM=20000
+
+% Allocation of registers
+
+% Here are macros for the automatic allocation of \count, \box, \dimen,
+% \skip, \muskip, and \toks registers, as well as \read and \write
+% stream numbers, \fam codes, \language codes, and \insert numbers.
+
+\message{registers,}
+
+% When a register is used only temporarily, it need not be allocated;
+% grouping can be used, making the value previously in the register return
+% after the close of the group. The main use of these macros is for
+% registers that are defined by one macro and used by others, possibly at
+% different nesting levels. All such registers should be defined through
+% these macros; otherwise conflicts may occur, especially when two or more
+% macro packages are being used at once.
+
+% The following counters are reserved:
+% 0 to 9 page numbering
+% 10 count allocation
+% 11 dimen allocation
+% 12 skip allocation
+% 13 muskip allocation
+% 14 box allocation
+% 15 toks allocation
+% 16 read file allocation
+% 17 write file allocation
+% 18 math family allocation
+% 19 language allocation
+% 20 insert allocation
+% 21 the most recently allocated number
+% 22 constant -1
+% New counters are allocated starting with 23, 24, etc. Other registers are
+% allocated starting with 10. This leaves 0 through 9 for the user to play
+% with safely, except that counts 0 to 9 are considered to be the page and
+% subpage numbers (since they are displayed during output). In this scheme,
+% \count 10 always contains the number of the highest-numbered counter that
+% has been allocated, \count 14 the highest-numbered box, etc.
+% Inserts are given numbers 254, 253, etc., since they require a \count,
+% \dimen, \skip, and \box all with the same number; \count 20 contains the
+% lowest-numbered insert that has been allocated. Of course, \box255 is
+% reserved for \output; \count255, \dimen255, and \skip255 can be used freely.
+
+% It is recommended that macro designers always use
+% \global assignments with respect to registers numbered 1, 3, 5, 7, 9, and
+% always non-\global assignments with respect to registers 0, 2, 4, 6, 8, 255.
+% This will prevent ``save stack buildup'' that might otherwise occur.
+
+\count10=22 % allocates \count registers 23, 24, ...
+\count11=9 % allocates \dimen registers 10, 11, ...
+\count12=9 % allocates \skip registers 10, 11, ...
+\count13=9 % allocates \muskip registers 10, 11, ...
+\count14=9 % allocates \box registers 10, 11, ...
+\count15=9 % allocates \toks registers 10, 11, ...
+\count16=-1 % allocates input streams 0, 1, ...
+\count17=-1 % allocates output streams 0, 1, ...
+\count18=3 % allocates math families 4, 5, ...
+\count19=0 % allocates \language codes 1, 2, ...
+\count20=255 % allocates insertions 254, 253, ...
+\countdef\insc@unt=20 % the insertion counter
+\countdef\allocationnumber=21 % the most recent allocation
+\countdef\m@ne=22 \m@ne=-1 % a handy constant
+\def\wlog{\immediate\write\m@ne} % write on log file (only)
+
+% Here are abbreviations for the names of scratch registers
+% that don't need to be allocated.
+
+\countdef\count@=255
+\dimendef\dimen@=0
+\dimendef\dimen@i=1 % global only
+\dimendef\dimen@ii=2
+\skipdef\skip@=0
+\toksdef\toks@=0
+
+% Now, we define \newcount, \newbox, etc. so that you can say \newcount\foo
+% and \foo will be defined (with \countdef) to be the next counter.
+% To find out which counter \foo is, you can look at \allocationnumber.
+% Since there's no \boxdef command, \chardef is used to define a \newbox,
+% \newinsert, \newfam, and so on.
+
+\outer\def\newcount{\alloc@0\count\countdef\insc@unt}
+\outer\def\newdimen{\alloc@1\dimen\dimendef\insc@unt}
+\outer\def\newskip{\alloc@2\skip\skipdef\insc@unt}
+\outer\def\newmuskip{\alloc@3\muskip\muskipdef\@cclvi}
+\outer\def\newbox{\alloc@4\box\chardef\insc@unt}
+\let\newtoks=\relax % we do this to allow plain.tex to be read in twice
+\outer\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
+\outer\def\newtoks{\alloc@5\toks\toksdef\@cclvi}
+\outer\def\newread{\alloc@6\read\chardef\sixt@@n}
+\outer\def\newwrite{\alloc@7\write\chardef\sixt@@n}
+\outer\def\newfam{\alloc@8\fam\chardef\sixt@@n}
+\outer\def\newlanguage{\alloc@9\language\chardef\@cclvi}
+\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
+ \ch@ck#1#4#2% make sure there's still room
+ \allocationnumber=\count1#1%
+ \global#3#5=\allocationnumber
+ \wlog{\string#5=\string#2\the\allocationnumber}}
+\outer\def\newinsert#1{\global\advance\insc@unt by\m@ne
+ \ch@ck0\insc@unt\count
+ \ch@ck1\insc@unt\dimen
+ \ch@ck2\insc@unt\skip
+ \ch@ck4\insc@unt\box
+ \allocationnumber=\insc@unt
+ \global\chardef#1=\allocationnumber
+ \wlog{\string#1=\string\insert\the\allocationnumber}}
+\def\ch@ck#1#2#3{\ifnum\count1#1<#2%
+ \else\errmessage{No room for a new #3}\fi}
+
+% Here are some examples of allocation.
+\newdimen\maxdimen \maxdimen=16383.99999pt % the largest legal <dimen>
+\newskip\hideskip \hideskip=-1000pt plus 1fill % negative but can grow
+\newskip\centering \centering=0pt plus 1000pt minus 1000pt
+\newdimen\p@ \p@=1pt % this saves macro space and time
+\newdimen\z@ \z@=0pt % can be used both for 0pt and 0
+\newskip\z@skip \z@skip=0pt plus0pt minus0pt
+\newbox\voidb@x % permanently void box register
+
+% And here's a different sort of allocation:
+% For example, \newif\iffoo creates \footrue, \foofalse to go with \iffoo.
+\outer\def\newif#1{\count@\escapechar \escapechar\m@ne
+ \expandafter\expandafter\expandafter
+ \def\@if#1{true}{\let#1=\iftrue}%
+ \expandafter\expandafter\expandafter
+ \def\@if#1{false}{\let#1=\iffalse}%
+ \@if#1{false}\escapechar\count@} % the condition starts out false
+\def\@if#1#2{\csname\expandafter\if@\string#1#2\endcsname}
+{\uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}} % `if' is required
+
+% Assign initial values to TeX's parameters
+
+\message{parameters,}
+
+% All of TeX's numeric parameters are listed here,
+% but the code is commented out if no special value needs to be set.
+% INITEX makes all parameters zero except where noted.
+
+\pretolerance=100
+\tolerance=200 % INITEX sets this to 10000
+\hbadness=1000
+\vbadness=1000
+\linepenalty=10
+\hyphenpenalty=50
+\exhyphenpenalty=50
+\binoppenalty=700
+\relpenalty=500
+\clubpenalty=150
+\widowpenalty=150
+\displaywidowpenalty=50
+\brokenpenalty=100
+\predisplaypenalty=10000
+% \postdisplaypenalty=0
+% \interlinepenalty=0
+% \floatingpenalty=0, set during \insert
+% \outputpenalty=0, set before TeX enters \output
+\doublehyphendemerits=10000
+\finalhyphendemerits=5000
+\adjdemerits=10000
+% \looseness=0, cleared by TeX after each paragraph
+% \pausing=0
+% \holdinginserts=0
+% \tracingonline=0
+% \tracingmacros=0
+% \tracingstats=0
+% \tracingparagraphs=0
+% \tracingpages=0
+% \tracingoutput=0
+\tracinglostchars=1
+% \tracingcommands=0
+% \tracingrestores=0
+% \language=0
+\uchyph=1
+% \lefthyphenmin=2 \righthyphenmin=3 set below
+% \globaldefs=0
+% \maxdeadcycles=25 % INITEX does this
+% \hangafter=1 % INITEX does this, also TeX after each paragraph
+% \fam=0
+% \mag=1000 % INITEX does this
+% \escapechar=`\\ % INITEX does this
+\defaulthyphenchar=`\-
+\defaultskewchar=-1
+% \endlinechar=`\^^M % INITEX does this
+\newlinechar=-1
+\delimiterfactor=901
+% \time=now % TeX does this at beginning of job
+% \day=now % TeX does this at beginning of job
+% \month=now % TeX does this at beginning of job
+% \year=now % TeX does this at beginning of job
+\showboxbreadth=5
+\showboxdepth=3
+\errorcontextlines=5
+
+\hfuzz=0.1pt
+\vfuzz=0.1pt
+\overfullrule=5pt
+\hsize=6.5in
+\vsize=8.9in
+\maxdepth=4pt
+\splitmaxdepth=\maxdimen
+\boxmaxdepth=\maxdimen
+% \lineskiplimit=0pt, changed by \normalbaselines
+\delimitershortfall=5pt
+\nulldelimiterspace=1.2pt
+\scriptspace=0.5pt
+% \mathsurround=0pt
+% \predisplaysize=0pt, set before TeX enters $$
+% \displaywidth=0pt, set before TeX enters $$
+% \displayindent=0pt, set before TeX enters $$
+\parindent=20pt
+% \hangindent=0pt, zeroed by TeX after each paragraph
+% \hoffset=0pt
+% \voffset=0pt
+
+% \baselineskip=0pt, changed by \normalbaselines
+% \lineskip=0pt, changed by \normalbaselines
+\parskip=0pt plus 1pt
+\abovedisplayskip=12pt plus 3pt minus 9pt
+\abovedisplayshortskip=0pt plus 3pt
+\belowdisplayskip=12pt plus 3pt minus 9pt
+\belowdisplayshortskip=7pt plus 3pt minus 4pt
+% \leftskip=0pt
+% \rightskip=0pt
+\topskip=10pt
+\splittopskip=10pt
+% \tabskip=0pt
+% \spaceskip=0pt
+% \xspaceskip=0pt
+\parfillskip=0pt plus 1fil
+
+\thinmuskip=3mu
+\medmuskip=4mu plus 2mu minus 4mu
+\thickmuskip=5mu plus 5mu
+
+% We also define special registers that function like parameters:
+\newskip\smallskipamount \smallskipamount=3pt plus 1pt minus 1pt
+\newskip\medskipamount \medskipamount=6pt plus 2pt minus 2pt
+\newskip\bigskipamount \bigskipamount=12pt plus 4pt minus 4pt
+\newskip\normalbaselineskip \normalbaselineskip=12pt
+\newskip\normallineskip \normallineskip=1pt
+\newdimen\normallineskiplimit \normallineskiplimit=0pt
+\newdimen\jot \jot=3pt
+\newcount\interdisplaylinepenalty \interdisplaylinepenalty=100
+\newcount\interfootnotelinepenalty \interfootnotelinepenalty=100
+
+% Definitions for preloaded fonts
+
+\def\magstephalf{1095 }
+\def\magstep#1{\ifcase#1 \@m\or 1200\or 1440\or 1728\or 2074\or 2488\fi\relax}
+
+\message{fonts (omitted),}
+
+\def\rm{\fam\z@\tenrm}
+\def\mit{\fam\@ne}
+\def\cal{\fam\tw@}
+\def\it{\fam4\tenit}
+\def\sl{\fam5\tensl}
+\def\bf{\fam6\tenbf}
+\def\tt{\fam7\tentt}
+
+% Macros for setting ordinary text
+\message{macros,}
+
+\def\frenchspacing{\sfcode`\.\@m \sfcode`\?\@m \sfcode`\!\@m
+ \sfcode`\:\@m \sfcode`\;\@m \sfcode`\,\@m}
+\def\nonfrenchspacing{\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000%
+ \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 }
+
+\def\normalbaselines{\lineskip\normallineskip
+ \baselineskip\normalbaselineskip \lineskiplimit\normallineskiplimit}
+
+\def\^^M{\ } % control <return> = control <space>
+\def\^^I{\ } % same for <tab>
+
+\def\lq{`} \def\rq{'}
+\def\lbrack{[} \def\rbrack{]}
+
+\let\endgraf=\par \let\endline=\cr
+
+\def\space{ }
+\def\empty{}
+\def\null{\hbox{}}
+
+\let\bgroup={ \let\egroup=}
+
+% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
+% since this allows, for example, `\let\par=\cr \obeylines \halign{...'
+{\catcode`\^^M=\active % these lines must end with %
+ \gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
+ \global\let^^M\par} % this is in case ^^M appears in a \write
+\def\obeyspaces{\catcode`\ \active}
+{\obeyspaces\global\let =\space}
+
+\def\loop#1\repeat{\def\body{#1}\iterate}
+\def\iterate{\body \let\next\iterate \else\let\next\relax\fi \next}
+\let\repeat=\fi % this makes \loop...\if...\repeat skippable
+
+\def\thinspace{\kern .16667em }
+\def\negthinspace{\kern-.16667em }
+\def\enspace{\kern.5em }
+
+\def\enskip{\hskip.5em\relax}
+\def\quad{\hskip1em\relax}
+\def\qquad{\hskip2em\relax}
+
+\def\smallskip{\vskip\smallskipamount}
+\def\medskip{\vskip\medskipamount}
+\def\bigskip{\vskip\bigskipamount}
+
+\def\nointerlineskip{\prevdepth-1000\p@}
+\def\offinterlineskip{\baselineskip-1000\p@
+ \lineskip\z@ \lineskiplimit\maxdimen}
+
+\def\topglue{\nointerlineskip\vglue-\topskip\vglue} % for top of page
+\def\vglue{\afterassignment\vgl@\skip@=}
+\def\vgl@{\par \dimen@\prevdepth \hrule height\z@
+ \nobreak\vskip\skip@ \prevdepth\dimen@}
+\def\hglue{\afterassignment\hgl@\skip@=}
+\def\hgl@{\leavevmode \count@\spacefactor \vrule width\z@
+ \nobreak\hskip\skip@ \spacefactor\count@}
+
+\def~{\penalty\@M \ } % tie
+\def\slash{/\penalty\exhyphenpenalty} % a `/' that acts like a `-'
+
+\def\break{\penalty-\@M}
+\def\nobreak{\penalty \@M}
+\def\allowbreak{\penalty \z@}
+
+\def\filbreak{\par\vfil\penalty-200\vfilneg}
+\def\goodbreak{\par\penalty-500 }
+\def\eject{\par\break}
+\def\supereject{\par\penalty-\@MM}
+
+\def\removelastskip{\ifdim\lastskip=\z@\else\vskip-\lastskip\fi}
+\def\smallbreak{\par\ifdim\lastskip<\smallskipamount
+ \removelastskip\penalty-50\smallskip\fi}
+\def\medbreak{\par\ifdim\lastskip<\medskipamount
+ \removelastskip\penalty-100\medskip\fi}
+\def\bigbreak{\par\ifdim\lastskip<\bigskipamount
+ \removelastskip\penalty-200\bigskip\fi}
+
+\def\line{\hbox to\hsize}
+\def\leftline#1{\line{#1\hss}}
+\def\rightline#1{\line{\hss#1}}
+\def\centerline#1{\line{\hss#1\hss}}
+
+\def\rlap#1{\hbox to\z@{#1\hss}}
+\def\llap#1{\hbox to\z@{\hss#1}}
+
+\def\m@th{\mathsurround\z@}
+\def\underbar#1{$\setbox\z@\hbox{#1}\dp\z@\z@
+ \m@th \underline{\box\z@}$}
+
+\newbox\strutbox
+\setbox\strutbox=\hbox{\vrule height8.5pt depth3.5pt width\z@}
+\def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
+
+\def\hidewidth{\hskip\hideskip} % for alignment entries that can stick out
+\def\ialign{\everycr{}\tabskip\z@skip\halign} % initialized \halign
+\newcount\mscount
+\def\multispan#1{\omit \mscount#1\relax
+ \loop\ifnum\mscount>\@ne \sp@n\repeat}
+\def\sp@n{\span\omit\advance\mscount\m@ne}
+
+\newif\ifus@ \newif\if@cr
+\newbox\tabs \newbox\tabsyet \newbox\tabsdone
+
+\def\cleartabs{\global\setbox\tabsyet\null \setbox\tabs\null}
+\def\settabs{\setbox\tabs\null \futurelet\next\sett@b}
+\let\+=\relax % in case this file is being read in twice
+\def\sett@b{\ifx\next\+\def\nxt{\afterassignment\s@tt@b\let\nxt}%
+ \else\let\nxt\s@tcols\fi \let\next\relax \nxt}
+\def\s@tt@b{\let\nxt\relax \us@false\m@ketabbox}
+\def\tabalign{\us@true\m@ketabbox} % non-\outer version of \+
+\outer\def\+{\tabalign}
+\def\s@tcols#1\columns{\count@#1\dimen@\hsize
+ \loop\ifnum\count@>\z@ \@nother \repeat}
+\def\@nother{\dimen@ii\dimen@ \divide\dimen@ii\count@
+ \setbox\tabs\hbox{\hbox to\dimen@ii{}\unhbox\tabs}%
+ \advance\dimen@-\dimen@ii \advance\count@\m@ne}
+
+\def\m@ketabbox{\begingroup
+ \global\setbox\tabsyet\copy\tabs
+ \global\setbox\tabsdone\null
+ \def\cr{\@crtrue\crcr\egroup\egroup
+ \ifus@\unvbox\z@\lastbox\fi\endgroup
+ \setbox\tabs\hbox{\unhbox\tabsyet\unhbox\tabsdone}}%
+ \setbox\z@\vbox\bgroup\@crfalse
+ \ialign\bgroup&\t@bbox##\t@bb@x\crcr}
+
+\def\t@bbox{\setbox\z@\hbox\bgroup}
+\def\t@bb@x{\if@cr\egroup % now \box\z@ holds the column
+ \else\hss\egroup \global\setbox\tabsyet\hbox{\unhbox\tabsyet
+ \global\setbox\@ne\lastbox}% now \box\@ne holds its size
+ \ifvoid\@ne\global\setbox\@ne\hbox to\wd\z@{}%
+ \else\setbox\z@\hbox to\wd\@ne{\unhbox\z@}\fi
+ \global\setbox\tabsdone\hbox{\box\@ne\unhbox\tabsdone}\fi
+ \box\z@}
+
+\def\hang{\hangindent\parindent}
+\def\textindent#1{\indent\llap{#1\enspace}\ignorespaces}
+\def\item{\par\hang\textindent}
+\def\itemitem{\par\indent \hangindent2\parindent \textindent}
+\def\narrower{\advance\leftskip\parindent
+ \advance\rightskip\parindent}
+
+\outer\def\beginsection#1\par{\vskip\z@ plus.3\vsize\penalty-250
+ \vskip\z@ plus-.3\vsize\bigskip\vskip\parskip
+ \message{#1}\leftline{\bf#1}\nobreak\smallskip\noindent}
+\outer\def\proclaim #1. #2\par{\medbreak
+ \noindent{\bf#1.\enspace}{\sl#2\par}%
+ \ifdim\lastskip<\medskipamount \removelastskip\penalty55\medskip\fi}
+
+\def\raggedright{\rightskip\z@ plus2em \spaceskip.3333em \xspaceskip.5em\relax}
+\def\ttraggedright{\tt\rightskip\z@ plus2em\relax} % for use with \tt only
+
+\chardef\%=`\%
+\chardef\&=`\&
+\chardef\#=`\#
+\chardef\$=`\$
+
+\def\leavevmode{\unhbox\voidb@x} % begins a paragraph, if necessary
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
+\def\AA{\leavevmode\setbox0\hbox{!}\dimen@\ht0\advance\dimen@-1ex%
+ \rlap{\raise.67\dimen@\hbox{\char'27}}A}
+
+\def\mathhexbox#1#2#3{\leavevmode
+ \hbox{$\m@th \mathchar"#1#2#3$}}
+
+\def\oalign#1{\leavevmode\vtop{\baselineskip\z@skip \lineskip.25ex%
+ \ialign{##\crcr#1\crcr}}} \def\o@lign{\lineskiplimit\z@ \oalign}
+\def\ooalign{\lineskiplimit-\maxdimen \oalign} % chars over each other
+{\catcode`p=12 \catcode`t=12 \gdef\\#1pt{#1}} \let\getf@ctor=\\
+\def\sh@ft#1{\dimen@#1\kern\expandafter\getf@ctor\the\fontdimen1\font
+ \dimen@} % kern by #1 times the current slant
+\def\d#1{{\o@lign{\relax#1\crcr\hidewidth\sh@ft{-1ex}.\hidewidth}}}
+\def\b#1{{\o@lign{\relax#1\crcr\hidewidth\sh@ft{-3ex}%
+ \vbox to.2ex{\hbox{\char22}\vss}\hidewidth}}}
+\def\c#1{{\setbox\z@\hbox{#1}\ifdim\ht\z@=1ex\accent24 #1%
+ \else\ooalign{\unhbox\z@\crcr\hidewidth\char24\hidewidth}\fi}}
+\def\copyright{{\ooalign{\hfil\raise.07ex\hbox{c}\hfil\crcr\Orb}}}
+
+\def\dots{\relax\ifmmode\ldots\else$\m@th\ldots\,$\fi}
+\def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX}
+
+\def\`#1{{\accent18 #1}}
+\def\'#1{{\accent19 #1}}
+\def\v#1{{\accent20 #1}} \let\^^_=\v
+\def\u#1{{\accent21 #1}} \let\^^S=\u
+\def\=#1{{\accent22 #1}}
+\def\^#1{{\accent94 #1}} \let\^^D=\^
+\def\.#1{{\accent95 #1}}
+\def\H#1{{\accent"7D #1}}
+\def\~#1{{\accent"7E #1}}
+\def\"#1{{\accent"7F #1}}
+\def\t#1{{\edef\next{\the\font}\the\textfont1\accent"7F\next#1}}
+
+\def\hrulefill{\leaders\hrule\hfill}
+\def\dotfill{\cleaders\hbox{$\m@th \mkern1.5mu.\mkern1.5mu$}\hfill}
+\def\rightarrowfill{$\m@th\smash-\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\mathord\rightarrow$}
+\def\leftarrowfill{$\m@th\mathord\leftarrow\mkern-7mu%
+ \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+ \mkern-7mu\smash-$}
+\mathchardef\braceld="37A \mathchardef\bracerd="37B
+\mathchardef\bracelu="37C \mathchardef\braceru="37D
+\def\downbracefill{$\m@th \setbox\z@\hbox{$\braceld$}%
+ \braceld\leaders\vrule height\ht\z@ depth\z@\hfill\braceru
+ \bracelu\leaders\vrule height\ht\z@ depth\z@\hfill\bracerd$}
+\def\upbracefill{$\m@th \setbox\z@\hbox{$\braceld$}%
+ \bracelu\leaders\vrule height\ht\z@ depth\z@\hfill\bracerd
+ \braceld\leaders\vrule height\ht\z@ depth\z@\hfill\braceru$}
+
+\outer\def\bye{\par\vfill\supereject\end}
+
+% Macros for math setting
+\message{math definitions,}
+
+\let\sp=^ \let\sb=_
+\def\,{\mskip\thinmuskip}
+\def\>{\mskip\medmuskip}
+\def\;{\mskip\thickmuskip}
+\def\!{\mskip-\thinmuskip}
+\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}}
+{\catcode`\'=\active \gdef'{^\bgroup\prim@s}}
+\def\prim@s{\prime\futurelet\next\pr@m@s}
+\def\pr@m@s{\ifx'\next\let\nxt\pr@@@s \else\ifx^\next\let\nxt\pr@@@t
+ \else\let\nxt\egroup\fi\fi \nxt}
+\def\pr@@@s#1{\prim@s} \def\pr@@@t#1#2{#2\egroup}
+{\catcode`\^^Z=\active \gdef^^Z{\not=}} % ^^Z is like \ne in math
+
+{\catcode`\_=\active \global\let_=\_} % _ in math is either subscript or \_
+
+\def\joinrel{\mathrel{\mkern-3mu}}
+\def\relbar{\mathrel{\smash-}} % \smash, because - has the same height as +
+\def\Relbar{\mathrel=}
+\def\bowtie{\mathrel\triangleright\joinrel\mathrel\triangleleft}
+\def\models{\mathrel|\joinrel=}
+\def\Longrightarrow{\Relbar\joinrel\Rightarrow}
+\def\longrightarrow{\relbar\joinrel\rightarrow}
+\def\longleftarrow{\leftarrow\joinrel\relbar}
+\def\Longleftarrow{\Leftarrow\joinrel\Relbar}
+\def\longmapsto{\mapstochar\longrightarrow}
+\def\longleftrightarrow{\leftarrow\joinrel\rightarrow}
+\def\Longleftrightarrow{\Leftarrow\joinrel\Rightarrow}
+\def\iff{\;\Longleftrightarrow\;}
+
+\def\ldots{\mathinner{\ldotp\ldotp\ldotp}}
+\def\cdots{\mathinner{\cdotp\cdotp\cdotp}}
+
+\def\skew#1#2#3{{\muskip\z@#1mu\divide\muskip\z@\tw@ \mkern\muskip\z@
+ #2{\mkern-\muskip\z@{#3}\mkern\muskip\z@}\mkern-\muskip\z@}{}}
+
+\def\bigl{\mathopen\big}
+\def\bigm{\mathrel\big}
+\def\bigr{\mathclose\big}
+\def\Bigl{\mathopen\Big}
+\def\Bigm{\mathrel\Big}
+\def\Bigr{\mathclose\Big}
+\def\biggl{\mathopen\bigg}
+\def\biggm{\mathrel\bigg}
+\def\biggr{\mathclose\bigg}
+\def\Biggl{\mathopen\Bigg}
+\def\Biggm{\mathrel\Bigg}
+\def\Biggr{\mathclose\Bigg}
+\def\big#1{{\hbox{$\left#1\vbox to8.5\p@{}\right.\n@space$}}}
+\def\Big#1{{\hbox{$\left#1\vbox to11.5\p@{}\right.\n@space$}}}
+\def\bigg#1{{\hbox{$\left#1\vbox to14.5\p@{}\right.\n@space$}}}
+\def\Bigg#1{{\hbox{$\left#1\vbox to17.5\p@{}\right.\n@space$}}}
+\def\n@space{\nulldelimiterspace\z@ \m@th}
+
+\def\choose{\atopwithdelims()}
+\def\brack{\atopwithdelims[]}
+\def\brace{\atopwithdelims\{\}}
+
+\def\mathpalette#1#2{\mathchoice{#1\displaystyle{#2}}%
+ {#1\textstyle{#2}}{#1\scriptstyle{#2}}{#1\scriptscriptstyle{#2}}}
+\newif\ifv@ \newif\ifh@
+\def\vphantom{\v@true\h@false\ph@nt}
+\def\hphantom{\v@false\h@true\ph@nt}
+\def\phantom{\v@true\h@true\ph@nt}
+\def\ph@nt{\ifmmode\def\next{\mathpalette\mathph@nt}%
+ \else\let\next\makeph@nt\fi\next}
+\def\makeph@nt#1{\setbox\z@\hbox{#1}\finph@nt}
+\def\mathph@nt#1#2{\setbox\z@\hbox{$\m@th#1{#2}$}\finph@nt}
+\def\finph@nt{\setbox\tw@\null
+ \ifv@ \ht\tw@\ht\z@ \dp\tw@\dp\z@\fi
+ \ifh@ \wd\tw@\wd\z@\fi \box\tw@}
+\def\mathstrut{\vphantom(}
+\def\smash{\relax % \relax, in case this comes first in \halign
+ \ifmmode\def\next{\mathpalette\mathsm@sh}\else\let\next\makesm@sh
+ \fi\next}
+\def\makesm@sh#1{\setbox\z@\hbox{#1}\finsm@sh}
+\def\mathsm@sh#1#2{\setbox\z@\hbox{$\m@th#1{#2}$}\finsm@sh}
+\def\finsm@sh{\ht\z@\z@ \dp\z@\z@ \box\z@}
+
+\def\cong{\mathrel{\mathpalette\@vereq\sim}} % congruence sign
+\def\@vereq#1#2{\lower.5\p@\vbox{\lineskiplimit\maxdimen\lineskip-.5\p@
+ \ialign{$\m@th#1\hfil##\hfil$\crcr#2\crcr=\crcr}}}
+\def\notin{\mathrel{\mathpalette\c@ncel\in}}
+\def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
+\def\rightleftharpoons{\mathrel{\mathpalette\rlh@{}}}
+\def\rlh@#1{\vcenter{\m@th\hbox{\ooalign{\raise2pt
+ \hbox{$#1\rightharpoonup$}\crcr
+ $#1\leftharpoondown$}}}}
+\def\buildrel#1\over#2{\mathrel{\mathop{\kern\z@#2}\limits^{#1}}}
+\def\doteq{\buildrel\textstyle.\over=}
+
+\def\cases#1{\left\{\,\vcenter{\normalbaselines\m@th
+ \ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}\right.}
+\def\matrix#1{\null\,\vcenter{\normalbaselines\m@th
+ \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
+ \mathstrut\crcr\noalign{\kern-\baselineskip}
+ #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
+\def\pmatrix#1{\left(\matrix{#1}\right)}
+\newdimen\p@renwd
+\setbox0=\hbox{\kern8.75002pt} \p@renwd=\wd0 % width of the big left (
+\def\bordermatrix#1{\begingroup \m@th
+ \setbox\z@\vbox{\def\cr{\crcr\noalign{\kern2\p@\global\let\cr\endline}}%
+ \ialign{$##$\hfil\kern2\p@\kern\p@renwd&\thinspace\hfil$##$\hfil
+ &&\quad\hfil$##$\hfil\crcr
+ \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}%
+ #1\crcr\omit\strut\cr}}%
+ \setbox\tw@\vbox{\unvcopy\z@\global\setbox\@ne\lastbox}%
+ \setbox\tw@\hbox{\unhbox\@ne\unskip\global\setbox\@ne\lastbox}%
+ \setbox\tw@\hbox{$\kern\wd\@ne\kern-\p@renwd\left(\kern-\wd\@ne
+ \global\setbox\@ne\vbox{\box\@ne\kern2\p@}%
+ \vcenter{\kern-\ht\@ne\unvbox\z@\kern-\baselineskip}\,\right)$}%
+ \null\;\vbox{\kern\ht\@ne\box\tw@}\endgroup}
+
+\def\openup{\afterassignment\@penup\dimen@=}
+\def\@penup{\advance\lineskip\dimen@
+ \advance\baselineskip\dimen@
+ \advance\lineskiplimit\dimen@}
+\def\eqalign#1{\null\,\vcenter{\openup\jot\m@th
+ \ialign{\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil
+ \crcr#1\crcr}}\,}
+\newif\ifdt@p
+\def\displ@y{\global\dt@ptrue\openup\jot\m@th
+ \everycr{\noalign{\ifdt@p \global\dt@pfalse \ifdim\prevdepth>-1000\p@
+ \vskip-\lineskiplimit \vskip\normallineskiplimit \fi
+ \else \penalty\interdisplaylinepenalty \fi}}}
+\def\@lign{\tabskip\z@skip\everycr{}} % restore inside \displ@y
+\def\displaylines#1{\displ@y \tabskip\z@skip
+ \halign{\hbox to\displaywidth{$\@lign\hfil\displaystyle##\hfil$}\crcr
+ #1\crcr}}
+\def\eqalignno#1{\displ@y \tabskip\centering
+ \halign to\displaywidth{\hfil$\@lign\displaystyle{##}$\tabskip\z@skip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\llap{$\@lign##$}\tabskip\z@skip\crcr
+ #1\crcr}}
+\def\leqalignno#1{\displ@y \tabskip\centering
+ \halign to\displaywidth{\hfil$\@lign\displaystyle{##}$\tabskip\z@skip
+ &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
+ &\kern-\displaywidth\rlap{$\@lign##$}\tabskip\displaywidth\crcr
+ #1\crcr}}
+
+% Definitions related to output
+
+\message{output routines,}
+
+\countdef\pageno=0 \pageno=1 % first page is number 1
+\newtoks\headline \headline={\hfil} % headline is normally blank
+\newtoks\footline \footline={\hss\tenrm\folio\hss}
+ % footline is normally a centered page number in font \tenrm
+\newif\ifr@ggedbottom
+\def\raggedbottom{\topskip 10\p@ plus60\p@ \r@ggedbottomtrue}
+\def\normalbottom{\topskip 10\p@ \r@ggedbottomfalse} % undoes \raggedbottom
+\def\folio{\ifnum\pageno<\z@ \romannumeral-\pageno \else\number\pageno \fi}
+\def\nopagenumbers{\footline{\hfil}} % blank out the footline
+\def\advancepageno{\ifnum\pageno<\z@ \global\advance\pageno\m@ne
+ \else\global\advance\pageno\@ne \fi} % increase |pageno|
+
+\newinsert\footins
+\def\footnote#1{\let\@sf\empty % parameter #2 (the text) is read later
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ #1\@sf\vfootnote{#1}}
+\def\vfootnote#1{\insert\footins\bgroup
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox \floatingpenalty\@MM
+ \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
+ \textindent{#1}\footstrut\futurelet\next\fo@t}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\egroup}
+\def\footstrut{\vbox to\splittopskip{}}
+\skip\footins=\bigskipamount % space added when footnote is present
+\count\footins=1000 % footnote magnification factor (1 to 1)
+\dimen\footins=8in % maximum footnotes per page
+
+\newinsert\topins
+\newif\ifp@ge \newif\if@mid
+\def\topinsert{\@midfalse\p@gefalse\@ins}
+\def\midinsert{\@midtrue\@ins}
+\def\pageinsert{\@midfalse\p@getrue\@ins}
+\skip\topins=\z@skip % no space added when a topinsert is present
+\count\topins=1000 % magnification factor (1 to 1)
+\dimen\topins=\maxdimen % no limit per page
+\def\@ins{\par\begingroup\setbox\z@\vbox\bgroup} % start a \vbox
+\def\endinsert{\egroup % finish the \vbox
+ \if@mid \dimen@\ht\z@ \advance\dimen@\dp\z@ \advance\dimen@12\p@
+ \advance\dimen@\pagetotal \advance\dimen@-\pageshrink
+ \ifdim\dimen@>\pagegoal\@midfalse\p@gefalse\fi\fi
+ \if@mid \bigskip\box\z@\bigbreak
+ \else\insert\topins{\penalty100 % floating insertion
+ \splittopskip\z@skip
+ \splitmaxdepth\maxdimen \floatingpenalty\z@
+ \ifp@ge \dimen@\dp\z@
+ \vbox to\vsize{\unvbox\z@\kern-\dimen@}% depth is zero
+ \else \box\z@\nobreak\bigskip\fi}\fi\endgroup}
+
+\output{\plainoutput}
+\def\plainoutput{\shipout\vbox{\makeheadline\pagebody\makefootline}%
+ \advancepageno
+ \ifnum\outputpenalty>-\@MM \else\dosupereject\fi}
+\def\pagebody{\vbox to\vsize{\boxmaxdepth\maxdepth \pagecontents}}
+\def\makeheadline{\vbox to\z@{\vskip-22.5\p@
+ \line{\vbox to8.5\p@{}\the\headline}\vss}\nointerlineskip}
+\def\makefootline{\baselineskip24\p@\lineskiplimit\z@\line{\the\footline}}
+\def\dosupereject{\ifnum\insertpenalties>\z@ % something is being held over
+ \line{}\kern-\topskip\nobreak\vfill\supereject\fi}
+
+\def\pagecontents{\ifvoid\topins\else\unvbox\topins\fi
+ \dimen@=\dp\@cclv \unvbox\@cclv % open up \box255
+ \ifvoid\footins\else % footnote info is present
+ \vskip\skip\footins
+ \footnoterule
+ \unvbox\footins\fi
+ \ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+\def\footnoterule{\kern-3\p@
+ \hrule width 2truein \kern 2.6\p@} % the \hrule is .4pt high
+
+% Hyphenation, miscellaneous macros, and initial values for standard layout
+\message{hyphenation}
+
+\lefthyphenmin=2 \righthyphenmin=3 % disallow x- or -xx breaks
+
+\def\magnification{\afterassignment\m@g\count@}
+\def\m@g{\mag\count@
+ \hsize6.5truein\vsize8.9truein\dimen\footins8truein}
+
+\def\loggingall{\tracingcommands\tw@\tracingstats\tw@
+ \tracingpages\@ne\tracingoutput\@ne\tracinglostchars\@ne
+ \tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen}
+\def\tracingall{\tracingonline\@ne\loggingall}
+
+\def\showhyphens#1{\setbox0\vbox{\parfillskip\z@skip\hsize\maxdimen\tenrm
+ \pretolerance\m@ne\tolerance\m@ne\hbadness0\showboxdepth0\ #1}}
+
+\normalbaselines
+\catcode`@=12 % at signs are no longer letters
+
diff --git a/macros/luatex/generic/minim/minim.doc b/macros/luatex/generic/minim/minim.doc
new file mode 100644
index 0000000000..d16250a0fe
--- /dev/null
+++ b/macros/luatex/generic/minim/minim.doc
@@ -0,0 +1,81 @@
+
+\input minim-doc.sty
+
+\startmetadata
+ author {Esger Renkema}
+ title {minim}
+ date {2021-06-01}
+ version {2021/1.0}
+ keywords {LuaTeX; Plain TeX; MetaPost; PDF/A; Tagged PDF; accessibility; a11y;
+ Unicode mathematics; XMP; metadata; hypertext; bookmarks}
+stopmetadata
+
+\maketitle
+
+This is a modern plain format for the LuaTeX engine, adding improved low-level
+support for many LuaTeX extensions and newer PDF features. While it can be
+used as drop-in replacement for plain TeX, it probably is most useful as
+a basis for your own formats.
+
+Most features included in the format are provided by separate packages that can
+be used on their own; see the packages
+
+\smallskip\marktableaslist \halign {\strut
+ \vrule height10ptdepth2ptwidth0pt\qquad
+ \red{#}\quad\hfil&#\hfil\cr
+minim-mp&for mplib (MetaPost) support\cr
+minim-math&for Unicode mathematics\cr
+minim-pdf&for hypertext and Tagged PDF\cr
+minim-xmp&for XMP (metadata) inclusion\cr}
+
+The documentation for the above packages will be replicated in separate
+chapters below.
+
+You can use this package by simply saying ⟦\input minim⟧; this will load the
+file \red{minim.tex}.
+For building your own format files, you can re-use the file \red{minim.ini}:
+if you define ⟦\fmtname⟧ before inputting this file, no ⟦\dump⟧ will be
+performed.
+
+
+\bigskip
+
+\tocfalse \section Contents \par \bigskip
+\begingroup \parskip1pt
+\protected\def\chapter#1#2#3{%
+ \stopelement{TOC}\smallskip
+ \nextpartag{}\red{\tenbf\marktocentry{#2}{}{\strut#1}{\hfill~}{#3}}%
+ \smallskip\startelement{TOC}}
+\protected\def\section#1#2#3{%
+ \marktocentry{#2}{}{\strut\quad#1}{\dotfill~}{#3}\par}
+\startelement{TOC} \startelement{TOC}
+\the\toc
+\stopelement{TOC} \stopelement{TOC}
+\endgroup
+
+\section Compatibility
+
+One central design goal of minim is to be as unobtrusive as possible: you
+should be able to safely ignore any function you do not want to use.
+Please get in touch if you find this not the case.
+
+Particular care has been taken to be compatible with \red{ltluatex}. All
+overlapping functions should produce the same results and ltluatex can be
+loaded either before or after minim.
+
+One point of incompatibility exists between \red{tikz/pgf} and the pattern
+functionality of minim-mp, due to conflicting implementations of pdf resource
+management.
+If you do not use filling patterns, however, the two packages can be used
+together.
+
+\licencesection
+
+\input minim-mp.doc
+\input minim-math.doc
+\input minim-pdf.doc
+\input minim-xmp.doc
+\input minim-alloc.doc
+
+\bye
+
diff --git a/macros/luatex/generic/minim/minim.ini b/macros/luatex/generic/minim/minim.ini
new file mode 100644
index 0000000000..26aed3a2c5
--- /dev/null
+++ b/macros/luatex/generic/minim/minim.ini
@@ -0,0 +1,25 @@
+
+% following luatex.ini
+\input luatexconfig
+\input luatexiniconfig
+\input load-unicode-data
+
+\input minim-plain
+
+\unless\ifdefined\fmtversion
+ \def\fmtversion{2021/1.0}\fi
+\suppressoutererror = 1
+
+\input minim-etex
+
+% and the actual minim
+\input minim
+
+% prepare default fonts
+\input minim-lmodern
+
+\unless\ifdefined\fmtname
+ \def\fmtname{minim}
+ \expandafter\dump\fi
+
+
diff --git a/macros/luatex/generic/minim/minim.pdf b/macros/luatex/generic/minim/minim.pdf
new file mode 100644
index 0000000000..715525bcf9
--- /dev/null
+++ b/macros/luatex/generic/minim/minim.pdf
Binary files differ
diff --git a/macros/luatex/generic/minim/minim.tex b/macros/luatex/generic/minim/minim.tex
new file mode 100644
index 0000000000..6003e52a85
--- /dev/null
+++ b/macros/luatex/generic/minim/minim.tex
@@ -0,0 +1,8 @@
+
+\input minim-alloc
+\input minim-mp
+\input minim-math
+\input minim-pdf
+\input minim-xmp
+
+