Compare commits

..

No commits in common. "main" and "master" have entirely different histories.
main ... master

52 changed files with 492 additions and 8365 deletions

View File

@ -1,38 +0,0 @@
name: CTAN upload
inputs:
filename:
required: true
dry-run:
required: true
uploader:
required: true
email:
required: true
version:
required: false
default: ${{ github.ref_name }}
runs:
using: composite
steps:
- name: Send to CTAN
uses: zauguin/ctan-upload@v0.1
with:
package-name: luamml
version: ${{ inputs.version }}
author: 'Marcel Krüger, LaTeX Project Team'
uploader: ${{ inputs.uploader }}
email: ${{ inputs.email }}
license: lppl1.3c
summary: "Automatically generate MathML from LuaLaTeX math mode material"
ctan-path: /macros/luatex/latex/luamml
support: https://github.com/latex3/luamml/issues
update: true
topic: maths,luatex
description: |
LuaMML is an experimental package to automatically generate a MathML representation of mathematical expessions written in LuaLaTeX documents. These MathML representations can be used for improving accessibility or to ease conversion into new output formats like HTML.
filename: ${{ inputs.filename }}
dry-run: ${{ inputs.dry-run }}
# announcement-filename: ctan.ann
note: Uploaded automatically by GitHub Actions.

60
.github/tl_packages vendored
View File

@ -1,60 +0,0 @@
scheme-minimal latex-bin l3build
#Proudly generated by the Island of TeX's DEPendency Printer https://gitlab.com/islandoftex/texmf/depp
alphalph
amsfonts
amsmath
bigintcalc
bitset
bookmark
booktabs
cm
colortbl
csquotes
enumitem
etoolbox
fancyvrb
firstaid
fontspec
gettitlestring
graphics
graphics-cfg
graphics-def
hologo
hycolor
hypdoc
hyperref
iftex
infwarerr
intcalc
knuth-lib
kvdefinekeys
kvoptions
kvsetkeys
l3backend
l3build
l3kernel
l3packages
l3experimental
latex
latex-fonts
latex-lab
lm
lm-math
ltxcmds
luacolor
lualatex-math
pdfescape
pdfmanagement-testphase
pdftexcmds
psnfss
refcount
rerunfilecheck
stringenc
symbol
tagpdf
tools
underscore
unicode-math
uniquecounter
url
zapfding

View File

@ -1,78 +0,0 @@
name: Release
on:
# Only triggers for new tags
push:
tags: "*"
jobs:
# Mostly the same as the main.yaml workflow, but we only use a single job
l3build:
runs-on: ubuntu-latest
steps:
# Boilerplate
- name: Checkout repository
uses: actions/checkout@v4
- run: sudo apt-get install tidy
- name: Install TeX Live
uses: zauguin/install-texlive@v3
with:
# Here we use the same list of packages as in the testing workflow.
package_file: .github/tl_packages
- name: Run l3build
run: l3build ctan -H --show-log-on-error
- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: Package
path: |
build/distrib/ctan/*.zip
ctan.ann
- name: Validate CTAN package
uses: ./.github/actions/ctan-upload
with:
uploader: Dummy Name
email: dryrun@example.com
filename: "build/distrib/ctan/luamml-ctan.zip"
dry-run: true
github:
runs-on: ubuntu-latest
needs:
- l3build
steps:
- name: Download package artifact
uses: actions/download-artifact@v4
with:
name: Package
- name: Create GitHub release
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5
id: release
with:
artifacts: "build/distrib/ctan/*.zip"
prerelease: ${{ endsWith(github.ref, '-dev') }}
token: ${{ secrets.GITHUB_TOKEN }}
# bodyFile: ctan.ann
ctan-upload:
if: "${{ !endsWith(github.ref, '-dev') }}"
runs-on: ubuntu-latest
environment: CTAN
needs:
- l3build
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
sparse-checkout: .github
- name: Download package artifact
uses: actions/download-artifact@v4
with:
name: Package
- name: Upload CTAN package
uses: ./.github/actions/ctan-upload
with:
uploader: ${{ secrets.CTAN_NAME }}
email: ${{ secrets.CTAN_EMAIL }}
filename: "build/distrib/ctan/luamml-ctan.zip"
dry-run: false

View File

@ -1,53 +0,0 @@
name: Automated testing
# Currently we run in two situations:
on:
# Whenever someone pushes to a branch or tag in our repo
push:
branches:
- "*"
# Whenever a pull request is opened, reopened or gets new commits.
pull_request:
# This implies that for every push to a local branch in our repo for which a
# pull request is open this runs twice. But it's important to ensure that pull
# requests get tested even if their branch comes from a fork.
jobs:
l3build:
runs-on: ubuntu-latest
strategy:
matrix:
kind: [doc, test]
name: "${{ format('{0}', matrix.kind == 'doc' && 'Documentation' || 'Test suite') }}"
steps:
# Boilerplate
- name: Checkout repository
uses: actions/checkout@v4
- run: sudo apt-get install tidy
- name: Install TeX Live
uses: zauguin/install-texlive@v3
with:
# The list of packages to install is in a separate file under .github/tl_packages
# to allow reuse.
package_file: .github/tl_packages
cache_version: 0
- name: Run l3build
run: ${{ format('l3build {0} -q -H', matrix.kind == 'doc' && 'doc' || 'check --show-log-on-error') }}
# Now we create the artifacts: There are two cases where this happens.
# 1. If we failed running tests
- name: Archive failed test output
if: ${{ matrix.kind == 'test' && always() }}
uses: zauguin/l3build-failure-artifacts@v1
with:
name: testfiles-${{ matrix.platform }}
# Decide how long to keep the test output artifact:
retention-days: 3
# 2. If we succeed building documentation
- name: Archive documentation
if: ${{ matrix.kind == 'doc' && success() }}
uses: actions/upload-artifact@v4
with:
name: Documentation
path: "**/*.pdf"
# Decide how long to keep the test output artifact:
retention-days: 21

5
.gitignore vendored
View File

@ -1,5 +0,0 @@
/build/
*.aux
*.log
*.pdf
*.xml

View File

@ -1,43 +0,0 @@
# Changelog
All notable changes to the `luamml` package since the
2025-02-17 will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
- Ulrike Fischer, 2025-03-06
* add class attribute to math environments
* correct columnalign (take label column into account)
* add intent :continued-row in split enviroment
* add intent :system-of-equations to environments
* temporary patch to \common@align@ending to store the environment name
* start some debugging functions (variable debugmtable)
* correct columnspacing
* add intent :pause-medium between columns
## 2025-02-21
- Ulrike Fischer, 2025-02-21
* change intent :equationlabel to :equation-label and
:noequationlabel to :no-equation-label
## 2025-02-17
### Changed
- Ulrike Fischer, 2025-02-17
* moved all patches into latex-lab
* added sockets to luamml.dtx
* changed handling of tags/labels: empty tags produces a row too and have an intent
* corrected small bugs
- Ulrike Fischer, 2024-11-29
luamml-structelemwriter.lua: moved the actualtext for e.g. stretched braces from the structure element to the mc-chunk.
- Ulrike Fischer, 2024-03-03
luamml.dtx: add plug for mbox socket to correctly annotate them in math.
- Ulrike Fischer, 2024-11-29
luamml-structelemwriter.lua: use structnum instead of label when stashing.

View File

@ -1,17 +1,14 @@
# LuaMML: Automated LuaLaTeX math to MathML conversion
# Automated LuaLaTeX math to MathML conversion
**Highly experimental! At this point all interfaces may change without prior warning and many features aren't implemented yet. It is not ready for anything beyond simple experiments.**
This is an attempt to implement automatic conversion of LuaLaTeX inline and display math expressions into MathML code to aid with tagging.
It works best with `unicode-math`, but it can also be used with traditional math fonts if mappings to Unicode are provided.
## Installation
Run `l3build install` to install `luamml` into your local `texmf` tree.
## Usage
Add `\usepackage[tracing]{luamml-demo}` to print MathML to the terminal or `\usepackage[files]{luamml-demo}` to generate separate files with MathML output.
Alternatively it can be used with latex-lab to automatically integrate with tagging infrastucture.
## Demo
Run `lualatex test_tex` to see all equations from [our example file](./test_tex.tex) converted into MathML.
## License
LuaMML may be modified and distributed under the terms of the [LaTeX Project Public License](https://www.latex-project.org/lppl/), version 1.3c or greater.
It is written by Marcel Krüger and the LaTeX Project Team.
<!-- Also see a [`tagpdf` experiment using this to tag PDF formulas](https://github.com/u-fischer/tagpdf/blob/develop/experiments/exp-mathml-lua.tex). -->
<!-- If you are very brave you can also try running `pdflatex test_pdf` and afterwards run `./pdfmml.lua test_pdf.lua` to get pdflatex formulas converted. -->
To test it on your own files, add `\usepackage{luamml}` and `\tracingmathml=2` to your preamble.
Also see a [`tagpdf` experiment using this to tag PDF formulas](https://github.com/u-fischer/tagpdf/blob/develop/experiments/exp-mathml-lua.tex).

View File

@ -2,14 +2,6 @@ module = "luamml"
tdsroot = "lualatex"
installfiles = { "luamml-*.lua", "*.sty" }
sourcefiles = { "luamml-*.lua", "*.sty", "*.dtx" }
typesetsuppfiles = { "*.tex" }
typesetsourcefiles = { "*.tex" }
stdengine = "luatex"
unpackfiles = { "*.dtx" }
typesetexe = "lualatex"
checkconfigs = {
'config-lua',
'config-pdf',
}
checkengines = {"luatex"}
sourcefiles = installfiles

View File

@ -1,17 +0,0 @@
testfiledir = "testfiles-lua"
checkengines = {"luatex"}
stdengine = "luatex"
checkruns = 3
test_types = test_types or {}
test_types.mml = {
test = '.mlt',
generated = '.mml',
reference = '.mlr',
expectation = '.mle',
rewrite = function(source, result, engine, errlevels)
return os.execute(string.format('tidy -xml -indent -wrap -quiet --output-file "%s" "%s"', result, source))
end,
}
test_order = {'log', 'pdf', 'mml'}

View File

@ -1,33 +0,0 @@
testfiledir = "testfiles-pdf"
checkengines = {"pdftex"}
stdengine = "pdftex"
checkruns = 3
test_types = test_types or {}
test_types.tml = {
test = '.xrt',
generated = '.tml',
reference = '.txr',
expectation = '.xre',
rewrite = function(source, result, engine, errlevels)
local file = assert(io.open(source,"rb"))
local content = string.gsub(file:read("*all") .. "\n","\r\n","\n")
file:close()
local new_content = content
-- local new_content = processor(content,...)
local newfile = io.open(result,"w")
newfile:write(new_content)
newfile:close()
end,
}
test_types.mml = {
test = '.mlt',
generated = '.tml',
reference = '.mlr',
expectation = '.mle',
rewrite = function(source, result, engine, errlevels)
return os.execute(string.format('texlua pdfmml.lua "%s" | tidy -xml -indent -wrap -quiet --output-file "%s" -', source, result))
end,
}
test_order = {'log', 'pdf', 'tml', 'mml'}

View File

@ -3,30 +3,11 @@ local make_root = require'luamml-convert'.make_root
local save_result = require'luamml-tex'.save_result
local store_column = require'luamml-table'.store_column
local store_tag = require'luamml-table'.store_tag
local store_notag = require'luamml-table'.store_notag
local get_table = require'luamml-table'.get_table
local set_row_attribute = require'luamml-table'.set_row_attribute
local to_text = require'luamml-lr'
local properties = node.get_properties_table()
local math_t = node.id'math'
local funcid = luatexbase.new_luafunction'__luamml_amsmath_add_last_to_row:'
token.set_lua('__luamml_amsmath_add_last_to_row:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
-- local box = token.scan_int()
local nest = tex.nest.top
local head, startmath = nest.head, nest.tail
repeat
startmath = startmath.prev
until startmath == head or (startmath.id == math_t and startmath.subtype == 0)
if startmath == head then return end
assert(startmath.id == node.id"math")
store_column(startmath)
end
local funcid = luatexbase.new_luafunction'__luamml_amsmath_add_box_to_row:'
token.set_lua('__luamml_amsmath_add_box_to_row:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
@ -34,139 +15,24 @@ lua.get_functions_table()[funcid] = function()
-- local box = token.scan_int()
local boxnum = 0
local startmath = tex.box[boxnum].list
assert(startmath.id == math_t)
store_column(startmath)
assert(startmath.id == node.id"math")
store_column(startmath, true)
end
local funcid = luatexbase.new_luafunction'__luamml_amsmath_set_row_columnalign:n'
token.set_lua('__luamml_amsmath_set_row_columnalign:n', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
set_row_attribute('columnalign', token.scan_argument())
end
-- This function is used to add a intent :continued-row to
-- rows of a split environment.
-- we assume that the table is a mtable with mrow with mtd.
-- we check row 2..n. If the first cell has only one element and
-- for this element 'tex:ignore' has been set, we assume a continued row and
-- set the intent on the mrow.
local function add_intent_continued_row (table)
for index,rowtable in ipairs(table) do
if table[index][1] and table[index][1][1] then -- just for safety ...
if index > 1 and #table[index][1]==1 and table[index][1][1]['tex:ignore'] then
table[index]['intent']=':continued-row'
end
end
end
end
-- This function add an intent =":pause-medium" on every second mtd in a table
-- currently it is also on the first (after the label) but this could be changed
-- used in __luamml_amsmath_finalize_table:n for
-- 'align' or 'alignat' or 'flalign' or 'xalignat' or 'xxalignat'
local function add_intent_pause (mmltable)
for mtrindex,mtrtable in ipairs(mmltable) do
for mtdindex,mtdtable in ipairs(mtrtable) do
if (mtdindex % 2 == 0) then
mtdtable['intent']=':pause-medium'
end
end
end
end
-- debug function for tables
-- activate with \directlua{debugmtable=2} or \directlua{debugmtable='split'}
local function debug_mtable (mtable,kind)
if debugmtable and (debugmtable==2) or (debugmtable==kind) then
texio.write_nl('==============')
texio.write_nl(kind)
texio.write_nl(table.serialize(mtable))
texio.write_nl('==============')
end
end
do
local saved
funcid = luatexbase.new_luafunction'__luamml_amsmath_save_inner_table:n'
token.set_lua('__luamml_amsmath_save_inner_table:n', funcid)
funcid = luatexbase.new_luafunction'__luamml_amsmath_finalize_table:'
token.set_lua('__luamml_amsmath_finalize_table:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local kind = token.scan_argument()
kind = kind:gsub("*","")
local mml_table = get_table()
if not mml_table then return end
mml_table.displaystyle = true
mml_table.class=kind
if kind=="split" then
add_intent_continued_row (mml_table)
end
local columns = node.count(node.id'align_record', tex.lists.align_head)//2
mml_table.columnalign = kind == 'gathered' and 'center' or string.rep('right left', columns, ' ')
local spacing = {}
for n in node.traverse_id(node.id'glue', tex.lists.align_head) do
spacing[#spacing+1] = n.width == 0 and '0' or string.format('%.3fpt', n.width/65781.76)
end
mml_table.columnspacing = #spacing > 3 and table.concat(spacing, ' ', 2, #spacing-2) or nil
debug_mtable(mml_table,kind)
saved = mml_table
end
funcid = luatexbase.new_luafunction'__luamml_amsmath_save_smallmatrix:'
token.set_lua('__luamml_amsmath_save_smallmatrix:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local mml_table = get_table()
mml_table.align = 'axis'
mml_table.class='smallmatrix'
mml_table.columnalign = 'center'
mml_table.columnspacing = '0.278em'
mml_table.rowspacing = string.format('%.3fpt', tex.lineskip.width/65781.76)
saved = {[0] = 'mpadded', width = '+0.333em', lspace = '0.167em', mml_table}
debug_mtable(mml_table,kind)
saved = mml_table
end
funcid = luatexbase.new_luafunction'__luamml_amsmath_finalize_inner_table:'
token.set_lua('__luamml_amsmath_finalize_inner_table:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local vcenter = tex.nest.top.tail.nucleus
local props = properties[vcenter]
if not props then
props = {}
properties[vcenter] = props
end
props.mathml_table = assert(saved)
saved = nil
end
end
funcid = luatexbase.new_luafunction'__luamml_amsmath_finalize_table:n'
token.set_lua('__luamml_amsmath_finalize_table:n', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local kind = token.scan_argument()
kind = kind:gsub("*","")
local mml_table = get_table()
if not mml_table then return end
mml_table.displaystyle = true
mml_table.class=kind
-- this should perhaps be configurable and extendable
if kind == 'align' or 'alignat' or 'flalign' or 'xalignat' or 'xxalignat' then
mml_table.intent=":system-of-equations"
add_intent_pause (mml_table)
end
local columns = node.count(node.id'align_record', tex.lists.align_head)//2
mml_table.columnalign = kind == 'align' and 'left '..string.rep('right left', columns, ' ') or nil
mml_table.width = kind == 'multline' and '100%' or nil
-- mml_table.side = kind == 'multline' and 'rightoverlap' or nil
mml_table.columnalign = string.rep('right left', columns, ' ')
local spacing = {}
for n in node.traverse_id(node.id'glue', tex.lists.align_head) do
spacing[#spacing+1] = n.width == 0 and '0' or '.8em'
end
mml_table.columnspacing = #spacing > 3 and "0 "..table.concat(spacing, ' ', 2, #spacing-2) or nil
debug_mtable(mml_table,kind)
mml_table.columnspacing = table.concat(spacing, ' ', 2, #spacing-2)
save_result(mml_table, true)
end
@ -184,9 +50,9 @@ funcid = luatexbase.new_luafunction'__luamml_amsmath_set_tag:'
token.set_lua('__luamml_amsmath_set_tag:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
if not last_tag then
store_notag({[0] = 'mtd',''})
else
texio.write_nl'WARNING: Tag extraction failed'
return
end
store_tag({[0] = 'mtd', last_tag})
last_tag = nil
end
end

View File

@ -54,7 +54,7 @@ end
local saved_array
funcid = luatexbase.new_luafunction'__luamml_array_save_array:'
funcid = luatexbase.new_luafunction'__luamml_array_finalize_array:'
token.set_lua('__luamml_array_save_array:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc.

View File

@ -11,86 +11,7 @@ local radical_t, fraction_t, fence_t = node.id'radical', node.id'fraction', node
local math_char_t, sub_box_t, sub_mlist_t = node.id'math_char', node.id'sub_box', node.id'sub_mlist'
local function invert_table(t)
local t_inv = {}
for k, v in next, t do
t_inv[v] = k
end
return t_inv
end
local noad_names = node.subtypes'noad'
--[[ We could determine the noad subtypes dynamically:
local noad_sub = invert_table(noad_names)
local noad_ord = noad_sub.ord
local noad_op = noad_sub.opdisplaylimits
local noad_oplimits = noad_sub.oplimits
local noad_opnolimits = noad_sub.opnolimits
local noad_bin = noad_sub.bin
local noad_rel = noad_sub.rel
local noad_open = noad_sub.open
local noad_close = noad_sub.close
local noad_punct = noad_sub.punct
local noad_inner = noad_sub.inner
local noad_under = noad_sub.under
local noad_over = noad_sub.over
local noad_vcenter = noad_sub.vcenter
-- But the spacing table depends on their specific values anyway, so we just verify the values
]]
local noad_ord, noad_op, noad_oplimits, noad_opnolimits = 0, 1, 2, 3
local noad_bin, noad_rel, noad_open, noad_close, noad_punct = 4, 5, 6, 7, 8
local noad_inner, noad_under, noad_over, noad_vcenter = 9, 10, 11, 12
for i, n in ipairs{'ord', 'opdisplaylimits', 'oplimits', 'opnolimits', 'bin',
'rel', 'open', 'close', 'punct', 'inner', 'under', 'over', 'vcenter'} do
assert(noad_names[i-1] == n)
end
-- Attention, the spacing_table is indexed by subtype+1 since 1-based tables are faster in Lua
local spacing_table = {
{0 , '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', 0 , 0 , 0 , '0.167em', 0 , 0 , 0 , },
{'0.167em', '0.167em', '0.167em', '0.167em', nil , '0.278em', 0 , 0 , 0 , '0.167em', '0.167em', '0.167em', '0.167em', },
nil,
nil,
{'0.222em', '0.222em', '0.222em', '0.222em', nil , nil , '0.222em', nil , nil , '0.222em', '0.222em', '0.222em', '0.222em', },
{'0.278em', '0.278em', '0.278em', '0.278em', nil , 0 , '0.278em', 0 , 0 , '0.278em', '0.278em', '0.278em', '0.278em', },
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{0 , '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', 0 , 0 , 0 , '0.167em', 0 , 0 , 0 , },
{'0.167em', '0.167em', '0.167em', '0.167em', nil , '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', },
{'0.167em', '0.167em', '0.167em', '0.167em', '0.222em', '0.278em', '0.167em', 0 , '0.167em', '0.167em', '0.167em', '0.167em', '0.167em', },
nil,
nil,
nil,
}
local spacing_table_script = {
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{'0.167em', '0.167em', '0.167em', '0.167em', nil , 0 , 0 , 0 , 0 , 0 , '0.167em', '0.167em', '0.167em', },
nil,
nil,
{0 , 0 , 0 , 0 , nil , nil , 0 , nil , nil , 0 , 0 , 0 , 0 , },
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{0 , 0 , 0 , 0 , nil , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
{0 , '0.167em', '0.167em', '0.167em', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , },
nil,
nil,
nil,
}
do -- Fill the blanks
local st, sts = spacing_table, spacing_table_script
local st_op, sts_op = st[noad_op+1], sts[noad_op+1]
st[noad_oplimits+1], sts[noad_oplimits+1] = st_op, sts_op
st[noad_opnolimits+1], sts[noad_opnolimits+1] = st_op, sts_op
local st_ord, sts_ord = st[noad_ord+1], sts[noad_ord+1]
st[noad_under+1], sts[noad_under+1] = st_ord, sts_ord
st[noad_over+1], sts[noad_over+1] = st_ord, sts_ord
st[noad_vcenter+1], sts[noad_vcenter+1] = st_ord, sts_ord
end
local noad_sub = node.subtypes'noad'
local radical_sub = node.subtypes'radical'
local fence_sub = node.subtypes'fence'
@ -104,13 +25,8 @@ local digit_map = {["0"] = true, ["1"] = true,
["5"] = true, ["6"] = true, ["7"] = true,
["8"] = true, ["9"] = true,}
local always_mo = {["%"] = true, ["&"] = true, ["."] = true, ["/"] = true,
["\\"] = true, ["¬"] = true, [""] = true, [""] = true, [""] = true,
[""] = true, [""] = true, [""] = true, [""] = true, ["|"] = true,
[""] = true, [""] = true, [""] = true, [""] = true, [""] = true,}
-- Marker tables replacing the core operator for space like elements
local space_like = {}
-- Two marker tables. They are used instead of an embellished operator to mark space-like or user provided constructs
local user_provided, space_like = {}, {}
local nodes_to_table
@ -119,71 +35,47 @@ local function sup_style(s) return s//4*2+4+s%2 end
-- The _to_table functions generally return a second argument which is
-- could be (if it were a <mo>) a core operator of the embellishe operator
-- or space_like
-- or space_like/user_provided
-- acc_to_table is special since it's return value should
-- always be considered a core operator
-- We ignore large_... since they aren't used for modern fonts
local function delim_to_table(delim)
if not delim then return end
local props = properties[delim]
local mathml_core = props and props.mathml_core
local mathml_table = props and (props.mathml_table or mathml_core)
if mathml_table ~= nil then return mathml_table, mathml_core end
local mathml_filter = props and props.mathml_filter -- Kind of pointless since the arguments are literals, but present for consistency
local props = properties[delim] props = props and props.mathml_table
if props then return props end
local char = delim.small_char
if char == 0 then
local result = {[0] = 'mspace', width = string.format("%.3fpt", tex.nulldelimiterspace/65781.76)}
if mathml_filter then
return mathml_filter(result, space_like)
else
return result, space_like
end
return {[0] = 'mspace', width = string.format("%.3fpt", tex.nulldelimiterspace/65781.76)}, space_like
else
local fam = delim.small_fam
char = remap_lookup[fam << 21 | char]
local result = {[0] = 'mo', char, ['tex:family'] = fam ~= 0 and fam or nil, stretchy = not stretchy[char] or nil, lspace = 0, rspace = 0, [':nodes'] = {delim}, [':actual'] = char}
if mathml_filter then
return mathml_filter(result, result)
else
local result = {[0] = 'mo', char, ['tex:family'] = fam ~= 0 and fam or nil, stretchy = not stretchy[char] or nil }
return result, result
end
end
end
-- Like kernel_to_table but always a math_char_t. Also creating a mo and potentially remapping to handle combining chars.
-- No lspace or space is set here since these never appear as core operators in an mrow.
-- Like kernel_to_table but always a math_char_t. Also creating a mo and potentially remapping to handle combining chars
local function acc_to_table(acc, cur_style, stretch)
if not acc then return end
local props = properties[acc]
local mathml_core = props and props.mathml_core
local mathml_table = props and (props.mathml_table or mathml_core)
if mathml_table ~= nil then return mathml_table, mathml_core end
local props = properties[acc] props = props and props.mathml_table
if props then return props end
if acc.id ~= math_char_t then
error'confusion'
end
local mathml_filter = props and props.mathml_filter -- Kind of pointless since the arguments are literals, but present for consistency
local fam = acc.fam
local char = remap_lookup[fam << 21 | acc.char]
char = remap_comb[char] or char
if stretch ~= not stretchy[char] then -- Handle nil gracefully in stretchy
stretch = nil
end
local result = {[0] = 'mo', char, ['tex:family'] = fam ~= 0 and fam or nil, stretchy = stretch, [':nodes'] = {acc}, [':actual'] = stretch and char or nil}
if mathml_filter then
return mathml_filter(result)
else
return result
end
return {[0] = 'mo', char, ['tex:family'] = fam ~= 0 and fam or nil, stretchy = stretch}
end
local function kernel_to_table(kernel, cur_style, text_families)
local function kernel_to_table(kernel, cur_style)
if not kernel then return end
local props = properties[kernel]
local mathml_core = props and props.mathml_core
local mathml_table = props and (props.mathml_table or mathml_core)
if mathml_table ~= nil then return mathml_table, mathml_core end
local mathml_filter = props and props.mathml_filter -- Kind of pointless since the arguments are literals, but present for consistency
local props = properties[kernel] props = props and props.mathml_table
if props then return props, user_provided end
local id = kernel.id
if id == math_char_t then
local fam = kernel.fam
@ -192,40 +84,27 @@ local function kernel_to_table(kernel, cur_style, text_families)
local result = {[0] = elem,
char,
['tex:family'] = fam ~= 0 and fam or nil,
mathvariant = utf8.len(char) == 1 and elem == 'mi' and utf8.codepoint(char) < 0x10000 and 'normal' or nil,
[':nodes'] = {kernel},
mathvariant = utf8.len(char) == 1 and elem == 'mi' and utf8.codepoint(char) < 0x10000 and 'normal' or nil
}
if mathml_filter then
return mathml_filter(result, result)
else
return result, result
end
elseif id == sub_box_t then
local result
if kernel.list.id == hlist_t then -- We directly give up for vlists
result = to_text(kernel.list.head)
else
result = {[0] = 'mi', {[0] = 'mglyph', ['tex:box'] = kernel.list, [':nodes'] = {kernel}}}
end
if mathml_filter then
return mathml_filter(result, result)
local result = to_text(kernel.list.head)
return result, result
else
local result = {[0] = 'mi', {[0] = 'mglyph', ['tex:box'] = kernel.list}}
return result, result
end
elseif id == sub_mlist_t then
if mathml_filter then
return mathml_filter(nodes_to_table(kernel.list, cur_style, text_families))
else
return nodes_to_table(kernel.list, cur_style, text_families)
end
return nodes_to_table(kernel.list, cur_style)
else
error'confusion'
end
end
local function do_sub_sup(t, core, n, cur_style, text_families)
local sub = kernel_to_table(n.sub, sub_style(cur_style), text_families)
local sup = kernel_to_table(n.sup, sup_style(cur_style), text_families)
local function do_sub_sup(t, core, n, cur_style)
local sub = kernel_to_table(n.sub, sub_style(cur_style))
local sup = kernel_to_table(n.sup, sup_style(cur_style))
if sub then
if sup then
return {[0] = 'msubsup', t, sub, sup}, core
@ -246,7 +125,7 @@ local function maybe_to_mn(noad, core)
local after = noad.next
if not after then return end
if after.id ~= noad_t then return end
if after.subtype ~= noad_ord then return end
if noad_sub[after.subtype] ~= 'ord' then return end
after = after.nucleus
if not after then return end
if after.id ~= math_char_t then return end
@ -254,91 +133,70 @@ local function maybe_to_mn(noad, core)
core[0] = 'mn'
end
local function noad_to_table(noad, sub, cur_style, joining, bin_replacements, text_families)
local nucleus, core = kernel_to_table(noad.nucleus, sub == noad_over and cur_style//2*2+1 or cur_style, text_families)
if not nucleus then return end
if core and core[0] == 'mo' and core.minsize and not core.maxsize then
core.maxsize = core.minsize -- This happens when a half-specified delimiter appears alone in a list.
-- If it has a minimal size, it should be fixed to that size (since there is nothing bigger in it's list)
end
if sub == noad_ord and not (bin_replacements[node.direct.todirect(noad)] or (nucleus == core and #core == 1 and always_mo[core[1]])) then
local function noad_to_table(noad, sub, cur_style, mn)
local class = noad_sub[sub]
local nucleus, core = kernel_to_table(noad.nucleus, class == 'over' and cur_style//2*2+1 or cur_style)
if class == 'ord' then
if core and core[0] == 'mo' then
core['tex:class'] = nil
if not core.minsize and not core.movablelimits then
core[0] = 'mi'
core.movablelimits = nil
core.mathvariant = #core == 1 and type(core[1]) == 'string' and utf8.len(core[1]) == 1 and utf8.codepoint(core[1]) < 0x10000 and 'normal' or nil
core.stretchy, core.lspace, core.rspace = nil
end
core.stretchy, core.mathvariant = nil, #core == 1 and type(core[0]) == 'string' and utf8.len(core[0]) == 1 and utf8.codepoint(core[0]) < -0x10000 and 'normal' or nil
core['tex:class'] = nil
end
if nucleus == core and #core == 1 then
if joining and joining[0] == 'mn' and core[0] == 'mi' and (core[1] == '.' or core[1] == ',') and maybe_to_mn(noad, core)
or core[0] == 'mn' or text_families[core['tex:family'] or 0] then
if joining and core[0] == joining[0] and core['tex:family'] == joining['tex:family'] then
joining[#joining+1] = core[1]
local cnodes = core[':nodes']
if cnodes then -- very likely
local jnodes = joining[':nodes']
if jnodes then -- very likely
table.move(cnodes, 1, #cnodes, #jnodes+1, jnodes)
if mn and core[0] == 'mi' and (core[1] == '.' or core[1] == ',') and maybe_to_mn(noad, core) or core[0] == 'mn' then
if mn then
mn[#mn+1] = core[1]
nucleus = do_sub_sup(mn, mn, noad, cur_style)
if nucleus == mn then
return nil, mn, mn
else
joining[':nodes'] = cnodes
end
end
nucleus = do_sub_sup(joining, joining, noad, cur_style, text_families)
if nucleus == joining then
return nil, joining, joining
else
return nucleus, joining, false
return nucleus, mn, false
end
elseif not noad.sub and not noad.sup then
return core, core, core
end
end
end
elseif sub == noad_op or sub == noad_oplimits or sub == noad_opnolimits or sub == noad_bin or sub == noad_rel or sub == noad_open
or sub == noad_close or sub == noad_punct or sub == noad_inner or sub == noad_ord then
elseif class == 'opdisplaylimits' or class == 'oplimits' or class == 'opnolimits' or class == 'bin' or class == 'rel' or class == 'open'
or class == 'close' or class == 'punct' or class == 'inner' then
if not core or not core[0] then
-- TODO
else
core[0] = 'mo'
if not core.minsize then
if stretchy[core[1]] then core.stretchy = false end
end
if core.mathvariant == 'normal' then core.mathvariant = nil end
core.lspace, core.rspace = 0, 0
end
nucleus['tex:class'] = noad_names[sub]
nucleus['tex:class'] = class
if (noad.sup or noad.sub) and (sub == noad_op or sub == noad_oplimits) then
if core and core[0] == 'mo' then core.movablelimits = sub == noad_op end
local sub = kernel_to_table(noad.sub, sub_style(cur_style), text_families)
local sup = kernel_to_table(noad.sup, sup_style(cur_style), text_families)
if (noad.sup or noad.sub) and (class == 'opdisplaylimits' or class == 'oplimits') then
nucleus.movablelimits = class == 'opdisplaylimits'
local sub = kernel_to_table(noad.sub, sub_style(cur_style))
local sup = kernel_to_table(noad.sup, sup_style(cur_style))
return {[0] = sup and (sub and 'munderover' or 'mover') or 'munder',
nucleus,
sub or sup,
sub and sup,
}, core
end
elseif sub == noad_under then
elseif class == 'under' then
return {[0] = 'munder',
nucleus,
{[0] = 'mo', '_',},
}, core
elseif sub == noad_over then
elseif class == 'over' then
return {[0] = 'mover',
nucleus,
{[0] = 'mo', '\u{203E}',},
}, core
elseif sub == noad_vcenter then -- Ignored. Nucleus will need special handling anyway
elseif class == 'vcenter' then -- Ignored. Nucleus will need special handling anyway
else
error[[confusion]]
end
return do_sub_sup(nucleus, core, noad, cur_style, text_families)
return do_sub_sup(nucleus, core, noad, cur_style)
end
local function accent_to_table(accent, sub, cur_style, text_families)
local nucleus, core = kernel_to_table(accent.nucleus, cur_style//2*2+1, text_families)
local function accent_to_table(accent, sub, cur_style)
local nucleus, core = kernel_to_table(accent.nucleus, cur_style//2*2+1)
local top_acc = acc_to_table(accent.accent, cur_style, sub & 1 == 1)
local bot_acc = acc_to_table(accent.bot_accent, cur_style, sub & 2 == 2)
return {[0] = top_acc and (bot_acc and 'munderover' or 'mover') or 'munder',
@ -360,18 +218,17 @@ style_table.crampedscript, style_table.crampedscriptscript =
style_table.display, style_table.text,
style_table.script, style_table.scriptscript
local function radical_to_table(radical, sub, cur_style, text_families)
local function radical_to_table(radical, sub, cur_style)
local kind = radical_sub[sub]
local nucleus, core = kernel_to_table(radical.nucleus, cur_style//2*2+1, text_families)
local nucleus, core = kernel_to_table(radical.nucleus, cur_style//2*2+1)
local left = delim_to_table(radical.left)
local elem
if kind == 'radical' or kind == 'uradical' then
-- FIXME: Check that this is really a square root
elem, core = {[0] = 'msqrt', nucleus, }, nil
elem, core = {[0] = 'msqrt', nucleus}, nil
elseif kind == 'uroot' then
-- FIXME: Check that this is really a root
-- UF 2024-12-04: force use of only one return value
elem, core = {[0] = 'mroot', nucleus, (kernel_to_table(radical.degree, 7, text_families))}, nil
elem, core = {[0] = 'msqrt', nucleus, kernel_to_table(radical.degree)}, nil
elseif kind == 'uunderdelimiter' then
elem, core = {[0] = 'munder', left, nucleus}, left
elseif kind == 'uoverdelimiter' then
@ -383,12 +240,12 @@ local function radical_to_table(radical, sub, cur_style, text_families)
else
error[[confusion]]
end
return do_sub_sup(elem, core, radical, cur_style, text_families)
return do_sub_sup(elem, core, radical, cur_style)
end
local function fraction_to_table(fraction, sub, cur_style, text_families)
local num, core = kernel_to_table(fraction.num, cur_style + 2 - cur_style//6*2, text_families)
local denom = kernel_to_table(fraction.denom, cur_style//2*2 + 3 - cur_style//6*2, text_families)
local function fraction_to_table(fraction, sub, cur_style)
local num, core = kernel_to_table(fraction.num, sup_style(cur_style))
local denom = kernel_to_table(fraction.denom, sub_style(cur_style))
local left = delim_to_table(fraction.left)
local right = delim_to_table(fraction.right)
local mfrac = {[0] = 'mfrac',
@ -415,31 +272,8 @@ end
local function fence_to_table(fence, sub, cur_style)
local delim, core = delim_to_table(fence.delim)
if core[0] ~= 'mo' then
return delim, core
end
core.fence, core.symmetric = 'true', 'true'
local options = fence.options
local axis
if fence.height ~= 0 or fence.depth ~= 0 then
axis = 0xA == options & 0xA
local exact = 0x18 == options & 0x18
-- We treat them always as exact. mpadded would allow us to support
-- non-exact ones too and I will implement that if I ever encounter
-- someone who does that intentionally. Until then, we warn people
-- since such fences are absurd.
if not exact then
texio.write_nl'luamml: The document uses a fence with \z
explicit dimensions but without the "exact" option. \z
This is probably a mistake.'
end
core.minsize = string.format("%.3fpt", (fence.height + fence.depth)/65781.76)
core.maxsize = core.minsize
else
axis = 0xC ~= options & 0xC
end
if not axis then
texio.write_nl'luamml: Baseline centered fence will be centered around math axis instead'
if delim[0] == 'mo' then
delim.fence = 'true'
end
return delim, core
end
@ -462,87 +296,67 @@ local function rule_to_table(rule, sub, cur_style)
if height == running_length then
height = '0.8em'
else
height = string.format("%.3fpt", height/65781.76)
height = height
end
local depth = rule.depth
if depth == running_length then
depth = '0.2em'
else
depth = string.format("%.3fpt", depth/65781.76)
depth = depth
end
return {[0] = 'mspace', mathbackground = 'currentColor', width = width, height = height, depth = depth}, space_like
end
-- The only part which changes the nodelist, we are converting bin into ord
-- nodes in the same way TeX would do it later anyway.
local function cleanup_mathbin(head)
local replacements = {}
local last = 'open' -- last sub if id was noad_t, left fence acts fakes being a open noad, bin are themselves. Every other noad is ord
for n, id, sub in node.traverse(head) do
if id == noad_t then
if sub == noad_bin then
if node.is_node(last) or last == noad_opdisplaylimits
or last == noad_oplimits or last == noad_opnolimits
or last == noad_rel or last == noad_open or last == noad_punct then
replacements[node.direct.todirect(n)] = true
n.subtype, last = noad_ord, noad_ord
else
last = n
end
else
if (sub == noad_rel or sub == noad_close or sub == noad_punct)
and node.is_node(last) then
replacements[node.direct.todirect(last)] = true
last.subtype = noad_ord
end
last = sub
end
elseif id == fence_t then
if sub == fence_sub.left then
last = noad_open
else
if node.is_node(last) then
replacements[node.direct.todirect(last)] = true
last.subtype = noad_ord, noad_ord
end
last = noad_ord
end
elseif id == fraction_t or id == radical_t or id == accent_t then
last = noad_ord
end
end
if node.is_node(last) then
replacements[node.direct.todirect(last)] = true
last.subtype = noad_ord
end
return replacements
end
function nodes_to_table(head, cur_style, text_families)
local bin_replacements = cleanup_mathbin(head)
function nodes_to_table(head, cur_style)
local t = {[0] = 'mrow'}
local result = t
local nonscript
local core, last_noad, last_core, joining = space_like, nil, nil, nil
local core, mn = space_like
local no_binop_context, last_noad, last_noad_core = true
for n, id, sub in node.traverse(head) do
local new_core, new_joining, new_node, new_noad
local props = properties[n]
local mathml_core = props and props.mathml_core
local mathml_table = props and (props.mathml_table or mathml_core)
if mathml_table ~= nil then
new_node, new_core = mathml_table, mathml_core
elseif id == noad_t then
local new_n
new_n, new_core, new_joining = noad_to_table(n, sub, cur_style, joining, bin_replacements, text_families)
if new_joining == false then
t[#t], new_joining = new_n, nil
else
new_node = new_n -- might be nil
if last_noad and ((id == noad_t and noad_sub[sub] == 'punct') or (id == fence_t and fence_sub[sub] ~= 'left')) then
last_noad['tex:class'], last_noad_core[0] = nil, 'mi'
last_noad_core.stretchy, last_noad_core.mathvariant = nil, #last_noad_core == 1
and type(last_noad_core[0]) == 'string'
and utf8.len(last_noad_core[0]) == 1
and utf8.codepoint(last_noad_core[0]) < -0x10000
and 'normal' or nil
end
local new_core, new_mn
local props = properties[n]
props = props and props.mathml_table
if props then
t[#t+1], new_core = props, user_provided
elseif id == noad_t then
local substr = noad_sub[sub]
if substr == 'bin' then
if no_binop_context then
sub, substr = 0, 'ord'
end
end
no_binop_context = false
or substr == 'bin'
or substr == 'opdisplaylimits'
or substr == 'oplimits'
or substr == 'opnolimits'
or substr == 'rel'
or substr == 'open'
or substr == 'punct'
local new_n
new_n, new_core, new_mn = noad_to_table(n, sub, cur_style, mn)
if new_mn == false then
t[#t], new_mn = new_n, nil
else
t[#t+1] = new_n -- might be nil
end
if substr == 'bin' then
last_noad, last_noad_core = new_n, new_core
else
last_noad, last_noad_core = nil, nil
end
new_noad = sub
elseif id == accent_t then
new_node, new_core = accent_to_table(n, sub, cur_style, text_families)
new_noad = noad_ord
t[#t+1], new_core = accent_to_table(n, sub, cur_style)
no_binop_context, last_noad, last_noad_core = false, nil, nil
elseif id == style_t then
if sub ~= cur_style then
if #t == 0 then
@ -562,78 +376,53 @@ function nodes_to_table(head, cur_style, text_families)
new_core = space_like
elseif id == choice_t then
local size = cur_style//2
new_node, new_core = nodes_to_table(n[size == 0 and 'display'
t[#t+1], new_core = nodes_to_table(n[size == 0 and 'display'
or size == 1 and 'text'
or size == 2 and 'script'
or size == 3 and 'scriptscript'
or assert(false)], 2*size, text_families), space_like
or assert(false)], 2*size), space_like
elseif id == radical_t then
new_node, new_core = radical_to_table(n, sub, cur_style, text_families)
new_noad = noad_ord
t[#t+1], new_core = radical_to_table(n, sub, cur_style)
no_binop_context, last_noad, last_noad_core = false, nil, nil
elseif id == fraction_t then
new_node, new_core = fraction_to_table(n, sub, cur_style, text_families)
new_noad = noad_inner
t[#t+1], new_core = fraction_to_table(n, sub, cur_style)
no_binop_context, last_noad, last_noad_core = false, nil, nil
elseif id == fence_t then
new_node, new_core = fence_to_table(n, sub, cur_style)
local class = n.class
new_noad = class >= 0 and class or sub == fence_sub.left and noad_open or noad_close
t[#t+1], new_core = fence_to_table(n, sub, cur_style)
no_binop_context, last_noad, last_noad_core = false, nil, nil
elseif id == kern_t then
if not nonscript then
new_node, new_core = space_to_table(n.kern, sub, cur_style)
t[#t+1], new_core = space_to_table(n.kern, sub, cur_style)
end
elseif id == glue_t then
if cur_style >= 4 or not nonscript then
if sub == 98 then -- TODO magic number
nonscript = true
else
new_node, new_core = space_to_table(n.width, sub, cur_style)
t[#t+1], new_core = space_to_table(n.width, sub, cur_style)
end
end
elseif id == rule_t then
new_node, new_core = rule_to_table(n, sub, cur_style)
t[#t+1], new_core = rule_to_table(n, sub, cur_style)
-- elseif id == disc_t then -- Uncommon, does not play nicely with math mode and no sensible mapping anyway
end -- The other possible ids are whatsit, penalty, adjust, ins, mark. Ignore them.
nonscript = nil
if core and new_core ~= space_like then
core = core == space_like and new_core or nil
end
if new_node then
if new_noad then
local space = last_noad and (cur_style >= 4 and spacing_table_script or spacing_table)[last_noad + 1][new_noad + 1] or 0
if assert(space) ~= 0 then
if new_core and new_core[0] == 'mo' then
new_core.lspace = space
elseif last_core and last_core[0] == 'mo' then
last_core.rspace = space
else
t[#t+1] = {[0] = 'mspace', width = space} -- TODO Move into operators whenever possible
mn = new_mn
end
end
last_noad, last_core = new_noad, new_core
elseif new_node[0] ~= 'mspace' or new_node.mathbackground then
last_core = nil
end
t[#t+1] = new_node
end
joining = new_joining
end
-- In TeX, groups are never space like, so we insert an artificial node instead.
-- This node should be ignored for most purposes
-- In TeX, groups are never space like
if core == space_like then
core = {[0] = 'mi', ['tex:ignore'] = 'true'}
core = {[0] = 'mi', intent = '@ignore'}
result[#result+1] = core
end
if t[0] == 'mrow' and #t == 1 then
assert(t == result)
result = t[1]
end
local mathml_filter = props and props.mathml_filter
if mathml_filter then
return mathml_filter(result, core)
else
return result, core
end
end
local function register_remap(family, mapping)
family = family << 21
@ -658,6 +447,6 @@ end
return {
register_family = register_remap,
process = function(head, style, families) return nodes_to_table(head, style or 2, families) end,
process = function(head, style) return nodes_to_table(head, style or 2) end,
make_root = to_math,
}

View File

@ -1,82 +0,0 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesExplPackage{luamml-demo}{2025-03-06}{0.5.0}{Reasonable default definitions for luamml}
\sys_if_engine_luatex:F {
\msg_new:nnn {luamml-demo} {pdftex-option-ignored} {Option~`#1'~is~being~ignored~in~pdfTeX~mode.}
\DeclareOption*{\msg_warning:nnx {luamml-demo} {pdftex-option-ignored} {\CurrentOption}}
\ProcessOptions\relax
\RequirePackage{luamml-pdf-demo}
\endinput
}
\RequirePackage{luamml}% Loading luamml is pretty much the point
\RequirePackage{amsmath,array}% These are more or less expected in luamml especially for advanced constructs
\AtBeginDocument{%
\@ifpackageloaded{unicode-math}{}{%
\RegisterFamilyMapping\symsymbols{oms}%
\RegisterFamilyMapping\symletters{oml}%
\RegisterFamilyMapping\symlargesymbols{omx}%
}
}
\bool_new:N \l__luamml_demo_structelem_bool
\DeclareOption{tracing}{
\tracingmathml=2
}
\DeclareOption{structelem}{
\bool_set_true:N \l__luamml_demo_structelem_bool
\luamml_structelem:
}
\DeclareOption{files}{
\int_new:N \g__luamml_demo_mathml_int
\luamml_set_filename:n {
\immediateassignment \int_gincr:N \g__luamml_demo_mathml_int
\jobname -formula- \int_use:N \g__luamml_demo_mathml_int .xml
}
}
\DeclareOption{l3build}{
\luamml_set_filename:n {
\jobname .mml
}
\luamml_begin_single_file:
}
\ProcessOptions\relax
\cs_new_eq:NN \LuaMMLSetFilename \luamml_set_filename:n
\cs_generate_variant:Nn \pdffile_filespec:nnn {ene}
\int_new:N \g__luamml_demo_af_int
\cs_new_protected:Npn \LuaMMLTagAF #1#2 {
\tag_mc_end_push:
\int_gincr:N \g__luamml_demo_af_int
\exp_args:Ne \pdf_object_new:nn{__luamml_demo_\int_use:N \g__luamml_demo_af_int}{dict}
\exp_args:Ne \tag_struct_begin:n{tag=Formula,AF=__luamml_demo_\int_use:N \g__luamml_demo_af_int,#1}
\bool_if:NF \l__luamml_demo_structelem_bool {
\tag_mc_begin:n{tag=Formula}
}
#2
\group_begin:
\pdfdict_put:nnn {l_pdffile/Filespec} {AFRelationship}{/Supplement}
\pdffile_filespec:ene
{ __luamml_demo_ \int_use:N \g__luamml_demo_af_int }
{ test.xml }
{ \luamml_get_last_mathml_stream:e{}\c_space_tl 0~R}
\group_end:
\bool_if:NF \l__luamml_demo_structelem_bool {
\tag_mc_end:
}
\tag_struct_end:
\tag_mc_begin_pop:n{}
}
\NewDocumentCommand\AnnotateFormula{ o m m }{%
\IfValueTF{#1}{%
\luamml_annotate:nen{#1}%
}{
\luamml_annotate:en
}{#2}{#3}
}
\cs_set_eq:NN \WriteoutFormula \luamml_pdf_write:

View File

@ -26,7 +26,6 @@ local remap_oml = { [0] =
0x1D465, 0x1D466, 0x1D467, 0x1D6A4, 0x1D6A5, 0x2118, 0x2192, nil,
}
-- Something fishy here. Starting with "3D the entries seem wrong
local remap_oms = { [0] =
0x2212, 0x22C5, 0xD7, 0x2A, 0xF7, 0x22C4, 0xB1, 0x2213,
0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x25CB, 0x2218, 0x2219,
@ -35,7 +34,7 @@ local remap_oms = { [0] =
0x2190, 0x2192, 0x2191, 0x2193, 0x2194, 0x2197, 0x2198, 0x2243,
0x21D0, 0x21D2, 0x21D1, 0x21D3, 0x21D4, 0x2196, 0x2199, 0x221D,
0x2032, 0x221E, 0x2208, 0x220B, 0x25B3, 0x25BD, 0x0338, 0x21A6,
0x2200, 0x2203, 0xAC, 0x2205, 0x211C, 0x2111, 0x22A4, 0x22A5,
0x2200, 0x2203, 0xAC, 0x2205, 0x211C, 0x22A9, 0x22A4, 0x22A5,
0x2135, 0x1D49C, 0x212C, 0x1D49E, 0x1D49F, 0x2130, 0x2131, 0x1D4A2,
0x210B, 0x2110, 0x1D4A5, 0x1D4A6, 0x2112, 0x2133, 0x1D4A9, 0x1D4AA,
0x1D4AB, 0x1D4AC, 0x211B, 0x1D4AE, 0x1D4AF, 0x1D4B0, 0x1D4B1, 0x1D4B2,

View File

@ -1,7 +1,7 @@
local properties = node.get_properties_table()
local function to_unicode(head, tail)
local result, subresult, i = {[0] = 'mtext'}, {}, 0
local result, subresult, i = {[0] = 'mrow'}, {}, 0
local characters, last_fid
local iter, state, n = node.traverse(head)
while true do
@ -10,7 +10,7 @@ local function to_unicode(head, tail)
local props = properties[n]
if props and props.glyph_info then
i = i+1
result[i] = glyph_info
subresult[i] = glyph_info
else
local char, fid = node.is_glyph(n)
if char then
@ -23,23 +23,27 @@ local function to_unicode(head, tail)
i = i+1
if uni then
if type(uni) == 'number' then
result[i] = utf.char(uni)
subresult[i] = utf.char(uni)
else
result[i] = utf.char(table.unpack(uni))
subresult[i] = utf.char(table.unpack(uni))
end
else
if char < 0x110000 then
result[i] = utf.char(char)
subresult[i] = utf.char(char)
else
result[i] = '\u{FFFD}'
subresult[i] = '\u{FFFD}'
end
end
elseif node.id'math' == id then
if props then
local mml = props.saved_mathml_table or props.saved_mathml_core
local mml = props.saved_mathml_table
if mml then
i = i+1
result[i] = mml
if i ~= 0 then
result[#result+1] = {[0] = 'mtext', table.concat(subresult)}
for j = i, 1, -1 do subresult[j] = nil end
i = 0
end
result[#result+1] = mml
n = node.end_of_math(n)
end
end
@ -48,23 +52,46 @@ local function to_unicode(head, tail)
elseif node.id'glue' == id then
if n.width > 1000 then -- FIXME: Coordinate constant with tagpdf
i = i+1
result[i] = '\u{00A0}' -- non breaking space... There is no real reason why it has to be non breaking, except that MathML often ignore other spaces
subresult[i] = '\u{00A0}' -- non breaking space... There is no real reason why it has to be non breaking, except that MathML often ignore other spaces
end
elseif node.id'hlist' == id then
local nested = to_unicode(n.head)
table.move(nested, 1, #nested, i+1, result)
i = i+#nested
if nested[0] == 'mtext' and #nested == 1 and type(nested[1]) == 'string' then
i=i+1
subresult[i] = nested[1]
else
if i ~= 0 then
result[#result+1] = {[0] = 'mtext', table.concat(subresult)}
for j = i, 1, -1 do subresult[j] = nil end
i = 0
end
if nested[0] == 'mrow' then
table.move(nested, 1, #nested, #result+1, result)
else -- should be unreachable (propbably actually is reachable if the inner list only contains math
result[#result+1] = nested
end
end
elseif node.id'vlist' == id then
i = i+1
result[i] = '\u{FFFD}'
subresult[i] = '\u{FFFD}'
elseif node.id'rule' == id then
if n.width ~= 0 then
i = i+1
result[i] = '\u{FFFD}'
subresult[i] = '\u{FFFD}'
end
end -- CHECK: Everything else can probably be ignored, otherwise shout at me
end
end
if i ~= 0 then
result[#result+1] = {[0] = 'mtext', table.concat(subresult)}
end
if #result == 0 then
local r = {[0] = 'mtext', ''}
return r, r
elseif #result == 1 then
result = result[1]
if result[1] == 'mtext' then return result, result end
end
return result
end

View File

@ -1,192 +1,8 @@
\ProvidesExplPackage {luamml-patches-amsmath} {2025-03-06} {0.5.0}
\ProvidesExplPackage {luamml-patches-amsmath} {2021-04-23} {0.0.1-alpha}
{Feel free to add a description here}
\lua_now:n { require'luamml-amsmath' }
% For all of these changes, the redefinitions appear huge.
% But they are almost identical to the original and only
% add luamml commands in appropriate places, so they would
% mostly disappear if there were enough hooks in amsmath.
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-02-24}
{}
{
\def\common@align@ending {
\math@cr \black@\totwidth@
\UseExpandableTaggingSocket {math/luamml/mtable/finalize} {\@currenvir}
\egroup
\ifingather@
\restorealignstate@
\egroup
\nonumber
\ifnum0=`{\fi\iffalse}\fi
\else
$$%
\fi
\ignorespacesafterend
}
}
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
{}
{
\PackageInfo{luamml}{patching~\string\start@aligned}
% aligned and friends
\cs_set:Npn \start@aligned #1#2 {
\RIfM@
\else
\nonmatherr@ { \begin { \@currenvir } }
\fi
\savecolumn@ % Assumption: called inside a group
\UseTaggingSocket{ math/luamml/annotate/false } {}{ \alignedspace@left }
\ams@start@box {#1} \bgroup
\maxfields@ #2 \relax
\ifnum \maxfields@ > \m@ne
\multiply \maxfields@ \tw@
\let \math@cr@@@ \math@cr@@@alignedat
\alignsep@ \z@skip
\else
\let \math@cr@@@ \math@cr@@@aligned
\alignsep@ \minalignsep
\fi
\Let@ \chardef \dspbrk@context \@ne
\default@tag
\spread@equation % no-op if already called
\global \column@ \z@
\ialign \bgroup
& \column@plus
\hfil
\strut@
$
\m@th
\displaystyle
{##}
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\tabskip \z@skip
& \column@plus
$
\m@th
\displaystyle
{
{}
##
}
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\hfil
\tabskip\alignsep@
\crcr
\ams@return@opt@arg
}
\PackageInfo{luamml}{patching~gathered}
\renewcommand \gathered [1] [c] {
\RIfM@
\else
\nonmatherr@ { \begin {gathered} }
\fi
\UseTaggingSocket{ math/luamml/annotate/false } {}{ \alignedspace@left }
\ams@start@box {#1} \bgroup
\Let@
\chardef \dspbrk@context \@ne
\restore@math@cr
\spread@equation
\ialign \bgroup
\hfil
\strut@
$
\m@th
\displaystyle
##
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\hfil
\crcr
\ams@return@opt@arg
}
\PackageInfo{luamml}{patching~\string\endaligned}
\cs_set:Npn \endaligned {
\crcr
\UseExpandableTaggingSocket{math/luamml/mtable/innertable/save}
\egroup
\restorecolumn@
\egroup
\UseTaggingSocket{math/luamml/mtable/innertable/finalize}
}
\PackageInfo{luamml}{patching~\string\gather@}
\cs_set:Npn \gather@ #1 {
\ingather@true
\let \split \insplit@
\let \tag \tag@in@align
\let \label \label@in@display
\chardef \dspbrk@context \z@
\intertext@ \displ@y@ \Let@
\let \math@cr@@@ \math@cr@@@gather
\gmeasure@ {#1}
\global \shifttag@false
\tabskip \z@skip
\global \row@ \@ne
\halign to \displaywidth \bgroup
\strut@
\setboxz@h {
$
\m@th
\displaystyle
{##}
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
$
}
\UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
\calc@shift@gather
\set@gather@field
\tabskip\@centering
&
\setboxz@h {
\strut@
{##}
}
\dim_compare:nNnTF {0pt} = {
\box_wd:N \c_zero_int
}
{ \place@tag@gather }
{
\place@tag@gather
\UseTaggingSocket{math/luamml/mtable/tag/set}
}
\tabskip \iftagsleft@
\gdisplaywidth@
\else
\z@skip
\span \fi
\crcr
#1
}
% in latex lab, add the luamml_ignore to \measuring@true instead.
\PackageInfo{luamml}{patching~\string\gmeasure@}
\cs_new_eq:NN \__luamml_amsmath_original_gmeasure:n \gmeasure@
\cs_set:Npn \gmeasure@ #1 {
\exp_last_unbraced:Nno
\use_ii_i:nn
{ \luamml_ignore: }
{ \__luamml_amsmath_original_gmeasure:n {#1} }
}
\PackageInfo{luamml}{patching~\string\endgather}
\cs_set:Npn \endgather {
\math@cr
\black@ \totwidth@
\UseExpandableTaggingSocket{math/luamml/mtable/finalize} {gather}
\egroup
$$
\ignorespacesafterend
}
% align and friends
\PackageInfo{luamml}{patching~\string\align@preamble}
\cs_set:Npn \align@preamble {
&
\hfil
@ -195,19 +11,20 @@
\@lign
$
\m@th
\displaystyle
{##}
\displaystyle {
##
}
\ifmeasuring@
\luamml_ignore:
\luamml_flag_ignore:
\else
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
\luamml_flag_save:
\fi
$
}
\ifmeasuring@
\savefieldlength@
\else
\UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
\__luamml_amsmath_add_box_to_row:
\fi
\set@field
\tabskip\z@skip
@ -222,22 +39,22 @@
##
}
\ifmeasuring@
\luamml_ignore:
\luamml_flag_ignore:
\else
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
\luamml_flag_save:
\fi
$
}
\ifmeasuring@
\savefieldlength@
\else
\UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
\__luamml_amsmath_add_box_to_row:
\fi
\set@field
\hfil
\tabskip\alignsep@
}
\PackageInfo{luamml}{patching~\string\math@cr@@@align}
\cs_set:Npn \math@cr@@@align {
\ifst@rred
\nonumber
@ -256,7 +73,7 @@
{ \make@display@tag }
}
\place@tag
\UseTaggingSocket{math/luamml/mtable/tag/set}
\__luamml_amsmath_set_tag:
\fi
\ifst@rred
\else
@ -266,175 +83,27 @@
\cr
}
% This was lost anyway, as the latex-lab code overwrites
% the definition again.
\PackageInfo{luamml}{patching~\string\maketag@@@}
\cs_set:Npn \maketag@@@ #1
{
\cs_set:Npn \maketag@@@ #1 {
\hbox {
\m@th
\normalfont
#1
\UseTaggingSocket{math/luamml/mtable/tag/save}
\__luamml_amsmath_save_tag:
}
}
\PackageInfo{luamml}{patching~\string\endalign}
% this handled in latex-lab through \common@align@ending
\cs_set:Npn \endalign {
\math@cr
\black@ \totwidth@
\UseTaggingSocket{math/luamml/mtable/finalize} {align}
\__luamml_amsmath_finalize_table:
\egroup
\ifingather@
\restorealignstate@
\egroup
\nonumber
\ifnum0=`{\fi\iffalse}\fi
\ifnum0={\fi\iffalse}\fi
\else
$$
\fi
\ignorespacesafterend
}
\PackageInfo{luamml}{patching~\string\multline@}
% For a more interesting one, let's consider multline:
\cs_new_eq:NN \__luamml_amsmath_original_multline:n \multline@
\cs_set:Npn \multline@ #1 {
\__luamml_amsmath_original_multline:n {
\ifmeasuring@ \else
\UseTaggingSocket{math/luamml/mtable/aligncol} {left}
\fi
#1
\ifmeasuring@ \else
\UseTaggingSocket{math/luamml/mtable/aligncol} {right}
\fi
}
}
%this is not move to latex-lab as the luamml_ignore is inserting with
% \measuringtrue
\PackageInfo{luamml}{patching~\string\mmeasure@}
\cs_new_eq:NN \__luamml_amsmath_original_mmeasure:n \mmeasure@
\cs_set:Npn \mmeasure@ #1 {
\exp_last_unbraced:Nno
\use_ii_i:nn
{ \luamml_ignore: }
{ \__luamml_amsmath_original_mmeasure:n {#1} }
}
% Luckily, {multline} uses \endmultline@math in exactly
% the spot where we have to set the flag.
% Less luckily, \endmultline@math sometimes get overwritten for the last line.
% But that isn't a problem since we want special behavior there anyway.
\PackageInfo{luamml}{patching~\string\endmultline@math}
\cs_set:Npn \endmultline@math {
\UseTaggingSocket{math/luamml/save/nNn}{{} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
}
\PackageInfo{luamml}{patching~\string\rendmultline@}
\cs_set:Npn \rendmultline@ {
\iftag@
\UseTaggingSocket{math/luamml/save/nNn}{{} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\let \endmultline@math \relax
\ifshifttag@
\hskip \multlinegap
\llap {
\vtop {
\raise@tag
\normalbaselines
\setbox \@ne \null
\dp \@ne \lineht@
\box \@ne
\hbox {
\strut@
\make@display@tag
}
}
}
\else
\hskip \multlinetaggap
\make@display@tag
\fi
\UseTaggingSocket{math/luamml/mtable/tag/set}
\else
\hskip \multlinegap
\fi
\hfilneg
\math@cr
\UseExpandableTaggingSocket {math/luamml/mtable/finalize} {multline}
\egroup
$$
}
\PackageInfo{luamml}{patching~\string\lendmultline@}
\cs_set:Npn \lendmultline@ {
\hfilneg
\hskip\multlinegap
\math@cr
\UseExpandableTaggingSocket {math/luamml/mtable/finalize} {multline}
%\__luamml_amsmath_finalize_table:n {multline}
\egroup
$$
}
\PackageInfo{luamml}{patching~smallmatrix}
\renewenvironment {smallmatrix} {
\UseTaggingSocket{ math/luamml/annotate/false } {} { \null\, }
\vcenter \bgroup
\Let@
\restore@math@cr
\default@tag
\baselineskip 6 \ex@
\lineskip 1.5 \ex@
\lineskiplimit \lineskip
\ialign \bgroup
\hfil
$
\m@th
\scriptstyle
##
% No \scriptsize here since we want to add the mstyle nodes
\UseTaggingSocket{math/luamml/save/nn}{ {} {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\hfil
&&
\thickspace
\hfil
$
\m@th
\scriptstyle
##
% No \scriptsize here since we want to add the mstyle nodes
\UseTaggingSocket{math/luamml/save/nn}{ {} {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\hfil
\crcr
}{%
\crcr
\UseExpandableTaggingSocket{math/luamml/mtable/smallmatrix/save}
\egroup
\egroup
\UseTaggingSocket{math/luamml/mtable/innertable/finalize}
\UseTaggingSocket{math/luamml/annotate/false} {}{ \, }
}
% {cases} is defined by the kernel, but we patch the overwritten version by amsmath.
\PackageInfo{luamml}{patching~\string\env@cases}
\cs_set:Npn \env@cases {
\let \@ifnextchar \new@ifnextchar
\left \lbrace
\def \arraystretch {1.2}
\array {@{}l@{\quad \luamml_ignore:}l@{}}
}
\PackageInfo{luamml}{patching~\string\bBigg@}
\cs_set:Npn \bBigg@ #1 #2 {
{
\ensuremath {
\Uvextensible height~#1 \big@size axis~exact~#2
}
}
}
} %end package test

View File

@ -1,29 +0,0 @@
\ProvidesExplPackage {luamml-patches-amstext} {2025-03-06} {0.5.0}
{patches of amstext commands}
% This is the same definition as in latex-lab-amsmath. It can go with the
% 2025-06-01 release.
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
{}
{
\PackageInfo{luamml}{patching~\string\text@}
\sys_if_engine_luatex:T
{
\def\text@#1{
\tag_socket_use:nnn {math/luamml/hbox}{}
{{%
\ifcase\mathstyle
\hbox{{#1}}\or
\hbox{{#1}}\or
\hbox{{#1}}\or
\hbox{{#1}}\or
\hbox{{\let\f@size\sf@size\selectfont#1}}\or
\hbox{{\let\f@size\sf@size\selectfont#1}}\or
\hbox{{\let\f@size\ssf@size\selectfont#1}}\or
\hbox{{\let\f@size\ssf@size\selectfont#1}}\or
\ERROR
\fi
\check@mathfonts
}}}
}
}

71
luamml-patches-array.sty Normal file
View File

@ -0,0 +1,71 @@
\ProvidesExplPackage {luamml-patches-array} {2021-04-23} {0.0.1-alpha}
{Feel free to add a description here}
\lua_now:n { require'luamml-array' }
\cs_set:Npn \@classz {
\@classx
\@tempcnta \count@
\prepnext@tok
\@addtopreamble {
\ifcase \@chnum
\hfil
\hskip 1sp
\d@llarbegin
\__luamml_array_init_col:
\insert@column
\luamml_flag_save:
\d@llarend
\__luamml_array_finalize_col:w 0~
\do@row@strut
\hfil
\or
\hskip 1sp
\d@llarbegin
\__luamml_array_init_col:
\insert@column
\luamml_flag_save:
\d@llarend
\__luamml_array_finalize_col:w 1~
\do@row@strut
\hfil
\or
\hfil
\hskip 1sp
\d@llarbegin
\__luamml_array_init_col:
\insert@column
\luamml_flag_save:
\d@llarend
\__luamml_array_finalize_col:w 2~
\do@row@strut
\or
\setbox \ar@mcellbox \vbox \@startpbox { \@nextchar }
\insert@column
\@endpbox
\ar@align@mcell
\do@row@strut
\or
\vtop \@startpbox { \@nextchar }
\insert@column
\@endpbox
\do@row@strut
\or
\vbox \@startpbox { \@nextchar }
\insert@column
\@endpbox
\do@row@strut
\fi
}
\prepnext@tok
}
\cs_set:Npn \endarray {
\crcr
\__luamml_array_save_array:
\egroup
\egroup
\__luamml_array_finalize_array:
\@arrayright
\gdef \@preamble {}
}

View File

@ -1,84 +0,0 @@
\ProvidesExplPackage {luamml-patches-kernel} {2025-03-06} {0.5.0}
{Feel free to add a description here}
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
{}
{
\PackageInfo{luamml}{patching~\string\mathsm@sh}
\cs_set:Npn \mathsm@sh #1 #2 {
\setbox \z@ \hbox {
$
\m@th #1 {
#2
}
\luamml_save:nNn {mathsmash} #1 {mpadded}
\luamml_pdf_write:
$
}
\luamml_annotate:nen {2} {
nucleus = true,
core = consume_label('mathsmash', function(padded)
padded.height, padded.depth = 0, 0~
end),
} {
{}
\finsm@sh
}
}
\PackageInfo{luamml}{patching~\string\mathph@nt}
\cs_set:Npn \mathph@nt #1 #2 {
\setbox \z@ = \hbox {
$
\m@th
#1
{#2}
\luamml_save:nNn {mathphant} #1 {mphantom}
$
}
\luamml_annotate:nen {1} {
nucleus = true,
core = {[0] = 'mpadded',
\ifh@\else
width = 0,
\fi
\ifv@\else
height = 0, depth = 0,
\fi
consume_label'mathphant',
}
} {
\finph@nt
}
}
\IfFileLoadedT {latex-lab-math.ltx} {
\RequirePackage{luamml-patches-lab-math}
}
}
% This is not moved to latex-lab for now. It doesn't work properly with structure elements
% active: the content is outside of the math.
\@ifpackageloaded {unicode-math} {} {
\cs_new:Npn \__luamml_kernel_define_character:Nnn #1#2#3 {
\cs_set:cpx { \cs_to_str:N #1 ~ } {
\luamml_annotate:nen {#2} {
nucleus = true, core = {[0] = 'mi', '\string\u{#3}'},
} {
\exp_not:v { \cs_to_str:N #1 ~ }
}
}
}
\__luamml_kernel_define_character:Nnn \models {3} {22a7}
\__luamml_kernel_define_character:Nnn \hookrightarrow {3} {21aa}
\__luamml_kernel_define_character:Nnn \hookleftarrow {3} {21a9}
\__luamml_kernel_define_character:Nnn \bowtie {3} {22c8}
\__luamml_kernel_define_character:Nnn \Longrightarrow {3} {27f9}
\__luamml_kernel_define_character:Nnn \longrightarrow {3} {27f6}
\__luamml_kernel_define_character:Nnn \Longleftarrow {3} {27f8}
\__luamml_kernel_define_character:Nnn \longleftarrow {3} {27f5}
\__luamml_kernel_define_character:Nnn \Longleftrightarrow {3} {27fa}
\__luamml_kernel_define_character:Nnn \longleftrightarrow {3} {27f7}
\__luamml_kernel_define_character:Nnn \longmapsto {4} {27fc}
}

View File

@ -1,27 +0,0 @@
\ProvidesExplPackage {luamml-patches-lab-math} {2025-03-06} {0.5.0}
{Feel free to add a description here}
% This definition is identical to the one in latex-lab-math.
% The redefinition and the whole patch file can be removed in 2025-06-01
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
{}
{
\AddToHook{begindocument} {
\PackageInfo{luamml}{patching~\string\common@align@ending}
\cs_set:Npn \common@align@ending {
\math@cr
\black@ \totwidth@
\UseExpandableTaggingSocket{math/luamml/mtable/finalize}{align}
\egroup
\ifingather@
\restorealignstate@
\egroup
\nonumber
\ifnum0=`{\fi\iffalse}\fi
\else
$$
\fi
\ignorespacesafterend
}
}
}

View File

@ -1,38 +0,0 @@
\ProvidesExplPackage {luamml-patches-mathtools} {2025-03-06} {0.5.0}
{Feel free to add a description here}
\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
{}
{
\RequirePackage{luamml-patches-amsmath}
% see https://github.com/latex3/tagging-project/issues/734
\renewcommand*\MT_mult_internal:n [1]{
\MH_if_boolean:nF {outer_mult}{\alignedspace@left} %<-- requires amsmath 2016/11/05
\MT_next:
\bgroup
\Let@
\def\l_MT_multline_lastline_fint{0 }
\chardef\dspbrk@context\@ne \restore@math@cr
\MH_let:NwN \math@cr@@\MT_mult_mathcr_atat:w
\MH_let:NwN \shoveleft\MT_shoveleft:wn
\MH_let:NwN \shoveright\MT_shoveright:wn
\spread@equation
\MH_set_boolean_F:n {mult_firstline}
\MT_measure_mult:n {#1}
\MH_if_dim:w \l_MT_multwidth_dim<\l_MT_multline_measure_fdim
\MH_setlength:dn \l_MT_multwidth_dim{\l_MT_multline_measure_fdim}
\fi
\MH_set_boolean_T:n {mult_firstline}
\MH_if_num:w \l_MT_multline_lastline_fint=\@ne
\MH_let:NwN \math@cr@@ \MT_mult_firstandlast_mathcr:w
\MH_fi:
\ialign\bgroup
\hfil\strut@$\m@th\displaystyle{}##
\UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
$
\UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
\hfil
\crcr
\hfilneg
#1
}
}

View File

@ -1,50 +0,0 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesExplPackage{luamml-pdf-demo}{2025-03-06}{0.5.0}{Reasonable default definitions for luamml-pdf}
\RequirePackage{luamml-pdf}% Loading luamml-pdf is pretty much the point
% \RequirePackage{amsmath,array}% May come back if the patches get ported
% Delay family mappings to allow for replacements
\AddToHook{begindocument/before}{%
\@ifpackageloaded{unicode-math}{}{%
\RegisterFamilyMapping\symsymbols{oms}%
\RegisterFamilyMapping\symletters{oml}%
\RegisterFamilyMapping\symlargesymbols{omx}%
}
}
\cs_new_protected:Npn \LuaMMLSetFilename #1 {}
% TODO.
% \cs_generate_variant:Nn \pdffile_filespec:nnn {ene}
% \int_new:N \g__luamml_demo_af_int
% \cs_new_protected:Npn \LuaMMLTagAF #1#2 {
% \int_gincr:N \g__luamml_demo_af_int
% \exp_args:Ne \pdf_object_new:nn{__luamml_demo_\int_use:N \g__luamml_demo_af_int}{dict}
% \exp_args:Ne \tagstructbegin{tag=Formula,AF=__luamml_demo_\int_use:N \g__luamml_demo_af_int,#1}
% \bool_if:NF \l__luamml_demo_structelem_bool {
% \tagmcbegin{tag=Formula}
% }
% #2
% \group_begin:
% \pdfdict_put:nnn {l_pdffile/Filespec} {AFRelationship}{/Supplement}
% \pdffile_filespec:ene
% { __luamml_demo_ \int_use:N \g__luamml_demo_af_int }
% { test.xml }
% { \luamml_get_last_mathml_stream:e{}\c_space_tl 0~R}
% \group_end:
% \bool_if:NF \l__luamml_demo_structelem_bool {
% \tagmcend
% }
% \tagstructend
% }
\NewDocumentCommand\AnnotateFormula{ o m m }{%
\IfValueTF{#1}{%
\luamml_annotate:nen{#1}%
}{
\luamml_annotate:en
}{#2}{#3}
}
\cs_set_eq:NN \WriteoutFormula \luamml_pdf_write:

View File

@ -1,143 +0,0 @@
local struct_begin = token.create'tag_struct_begin:n'
local struct_use = token.create'tag_struct_use:n'
local struct_use_num = token.create'tag_struct_use_num:n'
local struct_end = token.create'tag_struct_end:'
local mc_begin = token.create'tag_mc_begin:n'
local mc_end = token.create'tag_mc_end:'
local catlatex = luatexbase.registernumber("catcodetable@latex")
ltx = ltx or {}
ltx.__tag = ltx.__tag or {}
ltx.__tag.struct = ltx.__tag.struct or {}
ltx.__tag.struct.luamml = ltx.__tag.struct.luamml or {}
ltx.__tag.struct.luamml.labels = ltx.__tag.struct.luamml.labels or {}
local function escape_name(name)
return name
end
local function escape_string(str)
return str
end
local ltx
local function get_ltx()
if not ltx then
ltx = _ENV.ltx
if not ltx then
tex.error("LaTeX PDF support not loaded", {"Maybe try adding \\DocumentMetadata."})
ltx = {pdf = {object_id = function() return 0 end}}
end
end
return ltx
end
local mathml_ns_obj
local function get_mathml_ns_obj()
if not mathml_ns_obj then
mathml_ns_obj = get_ltx().pdf.object_id'tag/NS/mathml'
if not mathml_ns_obj then
tex.error("Failed to find MathML namespace", {"The PDF support does not know the mathml namespace"})
mathml_ns_obj = 0
end
end
return mathml_ns_obj
end
local attribute_counter = 0
local attributes = setmetatable({}, {__index = function(t, k)
attribute_counter = attribute_counter + 1
local attr_name = string.format('luamml_attr_%i', attribute_counter)
t[k] = attr_name
tex.runtoks(function()
tex.sprint(catlatex,string.format('\\tagpdfsetup{newattribute={%s}{/O/NSO/NS %i 0 R',
attr_name, mathml_ns_obj or get_mathml_ns_obj()))
-- tex.sprint(string.format('\\tagpdfsetup{newattribute={%s}{/O/MathML-3',
-- attr_name))
tex.cprint(12, k)
tex.sprint'}}'
end)
return attr_name
end})
local mc_type = luatexbase.attributes.g__tag_mc_type_attr
local mc_cnt = luatexbase.attributes.g__tag_mc_cnt_attr
-- print('!!!', mc_type, mc_cnt)
local stash_cnt = 0
local attrs = {}
local function write_elem(tree, stash)
if tree[':struct'] then
return tex.runtoks(function()
return tex.sprint(struct_use, '{', tree[':struct'], '}')
end)
end
if tree[':structnum'] then
return tex.runtoks(function()
return tex.sprint(struct_use_num, '{', tree[':structnum'], '}')
end)
end
if not tree[0] then print('ERR', require'inspect'(tree)) end
local i = 0
for attr, val in next, tree do if type(attr) == 'string' and not string.find(attr, ':') and attr ~= 'xmlns' then
-- for attr, val in next, tree do if type(attr) == 'string' and string.byte(attr) ~= 0x3A then
i = i + 1
attrs[i] = string.format('/%s(%s)', escape_name(attr), escape_string(val))
end end
table.sort(attrs)
if stash then
tree[':structnum'] = get_ltx().tag.get_struct_num_next()
stash = ', stash, '
end
local attr_flag = i ~= 0 and ', attribute=' .. attributes[table.concat(attrs)]
tex.sprint(struct_begin, '{tag=' .. tree[0] .. '/mathml')
if stash then tex.sprint(stash) end
if attr_flag then tex.sprint(attr_flag) end
tex.sprint'}'
for j = 1, i do attrs[j] = nil end
if tree[':nodes'] then
local n = tree[':nodes']
tex.runtoks(function()
if tree[':actual'] then
tex.sprint(mc_begin,'{tag=Span,actualtext=')
tex.cprint(12,tree[':actual'])
tex.sprint('}')
else
tex.sprint{mc_begin, string.format('{tag=%s}', tree[0])}
end
-- NOTE: This will also flush all previous sprint's... That's often annoying, but in this case actually intentional.
end)
local mct, mcc = tex.attribute[mc_type], tex.attribute[mc_cnt]
for i = 1, #n do
node.set_attribute(n[i], mc_type, mct)
node.set_attribute(n[i], mc_cnt, mcc)
end
tex.runtoks(function()
tex.sprint(mc_end)
end)
end
for _, elem in ipairs(tree) do
if type(elem) ~= 'string' and not elem['tex:ignore'] then
if elem['intent']==':equation-label' and ltx.__tag.struct.luamml.labels then
if #ltx.__tag.struct.luamml.labels > 0 then
-- print("CHECK LABEL STRUCTURE: ",table.serialize(elem), table.serialize(ltx.__tag.struct.luamml.labels))
local num= table.remove(ltx.__tag.struct.luamml.labels,1)
elem[1][#elem+1]={[':structnum']= num}
end
end
write_elem(elem)
end
end
tex.runtoks(function()
tex.sprint(struct_end)
end)
end
return function(element, stash)
return write_elem(element, stash)
end

View File

@ -4,23 +4,8 @@ local save_result = require'luamml-tex'.save_result
local properties = node.get_properties_table()
local glue_id = node.id'glue'
local tabskip_sub = 12
assert(node.subtypes'glue'[tabskip_sub] == 'tabskip')
local function store_get_row()
local row_temp
for i=tex.nest.ptr-1, 0, -1 do
local head = tex.nest[i].head
local glue = head.next
if glue and glue.id == glue_id and glue.subtype == tabskip_sub then
row_temp = head
break
end
end
if not row_temp then
error[[luamml_table's store function called outside of table]]
end
local row_temp = tex.nest[tex.nest.ptr-1].head
local props = properties[row_temp]
if not props then
props = {}
@ -35,7 +20,6 @@ local function store_get_row()
end
local function store_column_xml(mml, display)
if mml[0] ~= 'mtd' then
if display and mml[0] == 'mstyle' and mml.displaystyle == true then
mml[0], mml.displaystyle, mml.scriptlevel = 'mtd', nil, nil
else
@ -44,36 +28,24 @@ local function store_column_xml(mml, display)
end
mml = {[0] = 'mtd', mml}
end
end
table.insert(store_get_row(), mml)
return mml
end
local function store_column(startmath)
local function store_column(startmath, display)
local props = properties[startmath]
if not props then return end
local mml = props.saved_mathml_table or props.saved_mathml_core
if mml then return store_column_xml(mml) end
local mml = props.saved_mathml_table
if mml then return store_column_xml(mml, display) end
end
local function store_tag(xml)
local mml_row = store_get_row()
xml.intent = ':equation-label'
mml_row[0] = 'mlabeledtr'
table.insert(mml_row, 1, xml)
last_tag = nil
end
local function store_notag(xml)
local mml_row = store_get_row()
xml.intent = ':no-equation-label'
table.insert(mml_row, 1, xml)
end
local function set_row_attribute(name, value)
local mml_row = store_get_row()
mml_row[name] = value
end
luatexbase.add_to_callback('hpack_filter', function(_, group)
if group ~= 'fin_row' then return true end
@ -111,7 +83,5 @@ return {
store_column = store_column,
store_column_xml = store_column_xml,
store_tag = store_tag,
store_notag = store_notag,
set_row_attribute = set_row_attribute,
get_table = get_table,
}

View File

@ -1,140 +0,0 @@
local nest = tex.nest
local properties = node.get_properties_table()
local mark_environment = {
data = {
},
}
do
local _ENV = mark_environment
function consume_label(label, fn)
local mathml = data.mathml[label]
data.mathml[label] = nil
if fn then fn(mathml) end
return mathml
end
end
local function annotate()
local annotation, err = load( 'return {'
.. token.scan_argument()
.. '}', nil, 't', mark_environment)
if not annotation then
tex.error('Error while parsing LuaMML annotation', {err})
return 0
end
annotation = annotation()
local nesting = nest.top
local props = properties[nesting.head]
local current = props and props.luamml__annotate_context
if current then
current, props.luamml__annotate_context = current.head, current.prev
else
tex.error('Mismatched LuaMML annotation',
{'Something odd happened. Maybe you forgot braces around an annotated symbol in a subscript or superscript?'})
return 0
end
local after = nesting.tail
local count, offset = 0, annotation.offset
local marked
if current == after then
tex.error'Empty LuaMML annotation'
else
repeat
current = current.next
count = count + 1
if count == offset then
marked = current
elseif offset or current ~= after then
local props = properties[current]
if not props then
props = {}
properties[current] = props
end
props.mathml_table, props.mathml_core = nil, false
end
until current == after
if offset and not marked then
tex.error'Invalid offset in LuaMML annotation'
end
marked = marked or current
if annotation.nucleus then
marked = marked.nucleus
end
if marked then
local props = properties[marked]
if not props then
props = {}
properties[marked] = props
end
if annotation.core ~= nil then
props.mathml_core = annotation.core
end
if annotation.struct ~= nil then
local saved = props.mathml_filter
local struct = annotation.struct
function props.mathml_filter(mml, core)
mml[':struct'] = struct
if saved then
return saved(mml, core)
else
return mml, core
end
end
end
if annotation.structnum ~= nil then
local saved = props.mathml_filter
local structnum = annotation.structnum
function props.mathml_filter(mml, core)
mml[':structnum'] = structnum
if saved then
return saved(mml, core)
else
return mml, core
end
end
end
else
tex.error'Unable to annotate nucleus of node without nucleus'
end
end
return count
end
local funcid = luatexbase.new_luafunction'__luamml_annotate_begin:'
token.set_lua('__luamml_annotate_begin:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
local top = nest.top
local temp = top.head
local props = properties[temp]
if not props then
props = {}
properties[temp] = props
end
props.luamml__annotate_context = {
prev = props.luamml__annotate_context,
head = top.tail,
}
end
funcid = luatexbase.new_luafunction'__luamml_annotate_end:we'
token.set_lua('__luamml_annotate_end:we', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
local count = token.scan_int()
local real_count = annotate()
if count ~= real_count then
tex.error('Incorrect count in LuaMML annotation', {
'A LuaMML annotation was discovered with an explicit count \z
which was not the same as the number of top-level nodes annotated.',
string.format('This can be fixed by changing the supplied count from %i to %i \z
or by omitting the count value entirely.', count, real_count)
})
end
end
funcid = luatexbase.new_luafunction'__luamml_annotate_end:e'
token.set_lua('__luamml_annotate_end:e', funcid, 'protected')
lua.get_functions_table()[funcid] = annotate
return mark_environment

View File

@ -5,43 +5,8 @@ local register_family = mlist_to_mml.register_family
local mappings = require'luamml-legacy-mappings'
local write_xml = require'luamml-xmlwriter'
local write_struct = require'luamml-structelemwriter'
local filename_token = token.create'l__luamml_filename_tl'
local label_token = token.create'l__luamml_label_tl'
local left_brace = token.new(string.byte'{', 1)
local right_brace = token.new(string.byte'}', 2)
local output_hook_token
local global_text_families = {}
local text_families_meta = {__index = function(t, fam)
if fam == nil then return nil end
local assignment = global_text_families[fam]
if assignment == nil then
local fid = node.family_font(fam)
local fontdir = font.getfont(fid)
if not fontdir then
-- FIXME(?): If there is no font...
error'Please load your fonts?!?'
end
assignment = not (fontdir.MathConstants and next(fontdir.MathConstants))
end
t[fam] = assignment
return assignment
end}
local properties = node.get_properties_table()
local mmode, hmode, vmode do
local result, input = {}, tex.getmodevalues()
for k,v in next, tex.getmodevalues() do
if v == 'math' then mmode = k
elseif v == 'horizontal' then hmode = k
elseif v == 'vertical' then vmode = k
else assert(v == 'unset')
end
end
assert(mmode and hmode and vmode)
end
local funcid = luatexbase.new_luafunction'RegisterFamilyMapping'
token.set_lua('RegisterFamilyMapping', funcid, 'protected')
@ -50,128 +15,70 @@ lua.get_functions_table()[funcid] = function()
local mapping = token.scan_string()
if mappings[mapping] then
register_family(fam, mappings[mapping])
if global_text_families[fam] == nil then
global_text_families[fam] = false
end
else
tex.error(string.format('Unknown font mapping %q', mapping))
end
end
local funcid = luatexbase.new_luafunction'RegisterFamilyMapping'
token.set_lua('RegisterTextFamily', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
local fam = token.scan_int()
local _kind = token.scan_string()
global_text_families[fam] = true
end
local function shallow_copy(t)
local tt = {}
for k,v in next, t do
tt[k] = v
end
return tt
end
-- Possible flag values:
-- 0: Skip
-- 1: Generate MathML, but only save it for later usage in startmath node
-- 3: Normal (This is the only supported one in display mode)
-- 11: Generate MathML structure elements
-- 0: Normal (This is the only supported one in display mode)
-- 1: Like 0, result is display math
-- 2: Generate MathML, but only save it for later usage in startmath node
-- 3: Skip
-- 4: Prepend node list from buffer before generating
-- 5: Like 5, result is display math
-- 6: 2+4
-- 7: Skip but save copy of node list in buffer
--
-- More generally, flags is a bitfield with the defined bits:
-- Bit 5-7: See Bit 4
-- Bit 4: Overwrite mathstyle with bit 9-11
-- Bit 3: Generate MathML structure elements
-- Bit 2: Change root element name for saved element
-- Bit 1: Save MathML as a fully converted formula
-- Bit 0: Save MathML for later usage in startmath node. Ignored for display math.
-- In other words:
-- Bit 1: Suppress output
-- Bit 0: Force display if 1 isn't set, if it is then skip MathML generation
-- Bit 2: Integrate with table mechanism
local out_file
local mlist_buffer
local mlist_result, mlist_display
local mlist_result
local undefined_cmd = token.command_id'undefined_cs'
local call_cmd = token.command_id'call'
local labelled_mathml = {}
local function save_result(xml, display, structelem)
mlist_result = make_root(xml, display and 0 or 2)
if out_file then
out_file:write(write_xml(mlist_result, tex.count.l__luamml_pretty_int & 1 == 1):sub(2) .. '\n')
else
token.put_next(filename_token)
local filename = token.scan_argument()
if filename ~= '' then
assert(io.open(filename, 'w'))
:write(write_xml(mlist_result, tex.count.l__luamml_pretty_int & 1 == 1):sub(2) .. '\n')
:close()
local function save_result(xml, display)
mlist_result, mlist_display = xml, display
if tex.count.tracingmathml > 1 then
-- Here xml gets wrapped in an mrow to avoid modifying it.
texio.write_nl(write_xml(make_root({[0] = 'mrow', xml}, display and 0 or 2)) .. '\n')
end
end
local tracing = tex.count.tracingmathml > 1
if tracing then
texio.write_nl(write_xml(mlist_result, tex.count.l__luamml_pretty_int & 2 == 2) .. '\n')
end
if output_hook_token then
tex.runtoks(function()
tex.sprint(-2, output_hook_token, left_brace, write_xml(mlist_result, tex.count.l__luamml_pretty_int & 4 == 4), right_brace)
end)
end
if tex.count.l__luamml_flag_int & 8 == 8 then
write_struct(mlist_result)
end
return mlist_result
end
luatexbase.add_to_callback('pre_mlist_to_hlist_filter', function(mlist, style)
if tex.nest.top.mode == mmode then -- This is a equation label generated with \eqno
return true
end
local flag = tex.count.l__luamml_flag_int
if flag & 3 == 0 then
if flag & 3 == 3 then
if flag & 4 == 4 then
assert(mlist_buffer == nil)
mlist_buffer = node.copy_list(mlist)
end
return true
end
local display = style == 'display'
local startmath = tex.nest.top.tail -- Must come before any write_struct calls which adds nodes
style = flag & 16 == 16 and flag>>5 & 0x7 or display and 0 or 2
local xml, core = process_mlist(mlist, style, setmetatable({}, text_families_meta))
if flag & 2 == 2 then
xml = save_result(shallow_copy(xml), display)
end
local new_mlist, buffer_tail
if flag & 4 == 4 then
local element_type = token.get_macro'l__luamml_root_tl'
if element_type ~= 'mrow' then
if xml[0] == 'mrow' then
xml[0] = element_type
new_mlist, buffer_tail = assert(mlist_buffer), node.tail(mlist_buffer)
mlist.prev, buffer_tail.next = buffer_tail, mlist
mlist_buffer = nil
else
xml = {[0] = element_type, xml}
new_mlist = mlist
end
local xml = process_mlist(new_mlist, style == 'display' and 0 or 2)
if flag & 2 == 0 then
save_result(xml, style == 'display' or flag & 1 == 1)
end
end
if not display and flag & 1 == 1 then
if style == 'text' then
local startmath = tex.nest.top.tail
local props = properties[startmath]
if not props then
props = {}
properties[startmath] = props
end
props.saved_mathml_table, props.saved_mathml_core = xml, core
token.put_next(label_token)
local label = token.scan_argument()
if label ~= '' then
if labelled_mathml[label] then
tex.error('MathML Label already in use', {
'A MathML expression has a label which is already used by another \z
formula. If you do not want to label this formula with a unique \z
label, set a empty label instead.'})
else
labelled_mathml[label] = xml
end
end
if flag & 10 == 8 then
write_struct(xml, true) -- This modifies xml in-place to reference the struture element
props.saved_mathml_table = xml
end
if buffer_tail then
mlist.prev, buffer_tail.next = nil, nil
node.flush_list(new_mlist)
end
return true
end, 'dump_list')
@ -184,7 +91,7 @@ lua.get_functions_table()[funcid] = function()
"I was asked to provide MathML code for the last formula, but there weren't any new formulas since you last asked."
})
end
local mml = write_xml(mlist_result, tex.count.l__luamml_pretty_int & 8 == 8)
local mml = write_xml(make_root(mlist_result, mlist_display and 0 or 2))
if tex.count.tracingmathml == 1 then
texio.write_nl(mml .. '\n')
end
@ -192,41 +99,6 @@ lua.get_functions_table()[funcid] = function()
mlist_result = nil
end
funcid = luatexbase.new_luafunction'luamml_begin_single_file:'
token.set_lua('luamml_begin_single_file:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
token.put_next(filename_token)
local filename = token.scan_argument()
if filename ~= '' then
out_file = assert(io.open(filename, 'w'))
end
end
funcid = luatexbase.new_luafunction'luamml_end_single_file:'
token.set_lua('luamml_end_single_file:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
if out_file then
out_file:close()
out_file = nil
end
end
funcid = luatexbase.new_luafunction'luamml_register_output_hook:N'
token.set_lua('__luamml_register_output_hook:N', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
output_hook_token = token.get_next()
end
funcid = luatexbase.new_luafunction'luamml_disable_output_hook:'
token.set_lua('__luamml_disable_output_hook:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
output_hook_token = nil
end
local annotate_context = require'luamml-tex-annotate'
annotate_context.data.mathml = labelled_mathml
return {
save_result = save_result,
labelled = labelled_mathml,
}

View File

@ -10,9 +10,7 @@ local escapes = {
['&'] = "&amp;",
}
local function escape_text(text)
return string.gsub(string.gsub(tostring(text), '["<>&]', escapes), '[\x00-\x08\x0B\x0C\x0E-\x1F]', function(x)
return string.format('^^%02x', string.byte(x))
end)
return string.gsub(tostring(text), '("<>&)', escapes)
end
local attrs = {}
@ -21,11 +19,8 @@ local function write_elem(tree, indent)
local escaped_name = escape_name(assert(tree[0]))
local i = 0
for attr, val in next, tree do if type(attr) == 'string' then
if not string.find(attr, ':', 1, true) then
-- if string.byte(attr) ~= 0x3A then
i = i + 1
attrs[i] = string.format(' %s="%s"', escape_name(attr), escape_text(val))
end
end end
table.sort(attrs)
local out = string.format('%s<%s%s', indent or '', escaped_name, table.concat(attrs))
@ -34,25 +29,16 @@ local function write_elem(tree, indent)
return out .. '/>'
end
out = out .. '>'
-- Never indent the content if it's purely text.
if #tree == 1 and type(tree[1]) == 'string' then
indent = nil
end
local inner_indent = indent and indent .. ' '
local is_string
for _, elem in ipairs(tree) do
if type(elem) == 'string' then
if inner_indent and not is_string then
if inner_indent then
out = out .. inner_indent
end
out = out .. escape_text(elem)
is_string = true
else
if not elem['tex:ignore'] then
out = out .. write_elem(elem, inner_indent)
end
is_string = nil
end
end
if indent then out = out .. indent end
return out .. '</' .. escaped_name .. '>'
@ -60,5 +46,5 @@ end
return function(element, indent, version)
return (version == '11' and '<?xml version="1.1"?>' or '') ..
write_elem(element, indent and '\n' or nil)
write_elem(element, indent and '' or nil)
end

1006
luamml.dtx

File diff suppressed because it is too large Load Diff

32
luamml.sty Normal file
View File

@ -0,0 +1,32 @@
\ProvidesExplPackage {luamml} {2021-04-23} {0.0.1-alpha}
{Feel free to add a description here}
\int_new:N \l__luamml_flag_int
\int_new:N \tracingmathml
\lua_now:n { require'luamml-tex' }
\cs_new:Nn \luamml_flag_save: {
\int_set:Nn \l__luamml_flag_int { 2 }
}
\cs_new:Nn \luamml_flag_ignore: {
\int_set:Nn \l__luamml_flag_int { 3 }
}
\cs_new:Nn \luamml_flag_alignment_left: {
\int_set:Nn \l__luamml_flag_int { 7 }
}
\cs_new:Nn \luamml_flag_alignment_right: {
\int_set:Nn \l__luamml_flag_int { 6 }
}
\cs_new:Npn \__luamml_patch_package:nn #1 #2 {
\@ifpackageloaded {#1} {#2} {
\hook_gput_code:nnn {package/after/#1} {luamml} {#2}
}
}
\cs_new:Npn \__luamml_patch_package:n #1 {
\__luamml_patch_package:nn {#1} {
\RequirePackage { luamml-patches-#1 }
}
}
\__luamml_patch_package:n {amsmath}
\__luamml_patch_package:n {array}

View File

@ -1,39 +0,0 @@
local properties = {}
local subtypes = {
noad = {[0] = 'ord', 'opdisplaylimits', 'oplimits', 'opnolimits', 'bin', 'rel', 'open', 'close', 'punct', 'inner', 'under', 'over', 'vcenter'},
fence = {[0] = 'unset', 'left', 'middle', 'right', 'no'},
radical = {[0] = 'radical', 'uradical', 'uroot', 'uunderdelimiter', 'uoverdelimiter', 'udelimiterunder', 'udelimiterover'},
}
local function traverse_iter(context, head)
if head == nil then
head = context
else
head = head.next
end
if head then
return head, head.id, head.subtype
else
return nil
end
end
node = {
get_properties_table = function()
return properties
end,
id = function(name)
return name
end,
is_node = function(node)
return type(node) == 'table' and node.id and true or false
end,
subtypes = function(id)
return subtypes[id]
end,
traverse = function(head)
return traverse_iter, head, nil
end,
direct = {
todirect = function(n) return n end,
},
}
tex.nulldelimiterspace = tex.nulldelimiterspace or 78643 -- 1.2pt

View File

@ -1,61 +0,0 @@
local l = lpeg or require'lpeg'
local line = (1-l.P'\n')^0 * '\n'
local id = l.R'09'^1/tonumber
local non_final_list_block = (l.C((1-l.P'\n')^1) * '\n' - '### ' + '\n')^0
local math_lists_block = l.Ct('### ' * l.Cg(l.C'display' * ' ', 'display')^-1 * 'math mode entered at line ' * l.Cg(l.R'09'^1 / tonumber, 'line') * '\n'
* non_final_list_block)^1
local generic_list_block = '### ' * (line - 'current page:') * non_final_list_block
local luamml_block = l.Cg('LUAMML_FORMULA_BEGIN:' * id * ':' * l.Ct(
l.Cg(id, 'flag') * ':' * l.Cg((1-l.S':\n')^0, 'tag') * ':' * l.Cg((1-l.P'\n')^1, 'label')^-1 * l.P'\n'^1
* (math_lists_block + generic_list_block/0)^0
* (line - 'LUAMML_FORMULA_END\n')^0
* 'LUAMML_FORMULA_END\n') * l.Cc'groups')
local luamml_mark = l.Cg('LUAMML_MARK:' * id * ':' * l.Cs((1 - l.P'\n' + l.Cg('\n' * l.Cc'' - '\nLUAMML_MARK_END\n'))^0) * '\nLUAMML_MARK_END\n' * l.Cc'marks')
local function add(a, b) return a + b end
local count_block = '### ' * line * l.Cf(l.Cc(0) * (('\\' * l.Cc(1))^-1 * line - '### ')^0, add)
local luamml_precount = l.Cg('LUAMML_COUNT:' * id * l.P'\n'^1
* count_block * l.Cc'precount')
local luamml_postcount = l.Cg('LUAMML_COUNT_END:' * id * l.P'\n'^1
* count_block * l.Cc'postcount')
local luamml_instruction = l.Cg('LUAMML_INSTRUCTION:' * l.Cc(nil) * l.C((1 - l.P'\n')^0) * '\n' * l.Cc'instructions')
local function multi_table_set(t, key, value, table)
table = t[table]
table[key or #table + 1] = value
return t
end
local log_file = l.Cf(l.Ct(l.Cg(l.Ct'', 'groups')
* l.Cg(l.Ct'', 'precount')
* l.Cg(l.Ct'', 'postcount')
* l.Cg(l.Ct'', 'marks')
* l.Cg(l.Ct'', 'instructions'))
* (luamml_block + luamml_mark + luamml_instruction + luamml_precount + luamml_postcount + line)^0,
multi_table_set)
return function(filename)
local f
if filename and filename ~= '-' then
local msg f, msg = assert(io.open(filename, 'r'))
if not f then return f, msg end
end
local content = (f or io.stdin):read'a'
if f then f:close() end
-- The following does *not* end with * -1 since we want to allow the last line to not end with \n.
-- In that case we ignore the last line, but that's safe since the last line never contains our markers.
local parsed = assert(log_file:match(content))
local precount, postcount, count = parsed.precount, parsed.postcount, {}
for id, pre in next, precount do
local post = assert(postcount[id], 'Unbalanced count')
count[id], postcount[id] = post-pre, nil
end
assert(not next(postcount), 'Unbalanced count')
parsed.precount, parsed.postcount, parsed.count = nil, nil, count
return parsed
end

View File

@ -1,234 +0,0 @@
require'pdfmml-emulate-node'
local properties = node.get_properties_table()
local l = lpeg or require'lpeg'
local hex_digit = l.R('09', 'af')
local function hex_to_int(s) return tonumber(s, 16) end
local tex_char = l.Cg('^^' * (hex_digit * hex_digit / hex_to_int
+ l.R'\0\x3F' / function(s) return s:byte() + 0x40 end
+ l.R'\x40\x7F' / function(s) return s:byte() - 0x40 end)
+ l.P(1) / string.byte)
local scaled = l.P'-'^-1 * l.R'09'^1 * '.' * l.R'09'^1 / function(s) return (tonumber(s * 0x10000) + .5) // 1 end
local int = l.P'-'^-1 * l.R'09'^1 / tonumber
local glue_order_mu = 'filll' * l.Cc(3)
+ 'fill' * l.Cc(2)
+ 'fil' * l.Cc(1)
+ 'mu' * l.Cc(0)
local glue_order_pt = 'filll' * l.Cc(3)
+ 'fill' * l.Cc(2)
+ 'fil' * l.Cc(1)
+ 'pt' * l.Cc(0)
local glue_order = 'filll' * l.Cc(3)
+ 'fill' * l.Cc(2)
+ 'fil' * l.Cc(1)
+ l.Cc(0)
local delimiter_code = '"' * (l.R('09', 'AF')^1 / function(s)
local code = tonumber(s, 16)
return {id = 'delim',
small_fam = (code >> 20) & 0xF,
small_char = (code >> 12) & 0xFF,
large_fam = (code >> 8) & 0xF,
large_char = code & 0xFF,
}
end)
local balanced_braces = l.Ct{'{' * (1-l.S'{}'+l.V(1))^0 * '}'}
local math_char = l.Ct('\\fam' * l.Cg(l.R'09'^1 / tonumber, 'fam') * ' ' * l.Cg(tex_char, 'char') * l.Cg(l.Cc'math_char', 'id'))
local hdw = '(' * l.Cg(scaled + '*' * l.Cc(-0x40000000), 'height') * '+' * l.Cg(scaled + '*' * l.Cc(-0x40000000), 'depth') * ')x' * l.Cg(scaled + '*' * l.Cc(-0x40000000), 'width')
local generic_simple_node = l.Ct('\\' * (
l.Cg('rule', 'id') * hdw
+ l.Cg('kern', 'id') * l.Cg(' ' * l.Cc(1) + l.Cc(0), 'subtype') * l.Cg(scaled, 'kern') * (' (for ' * (l.R'az' + l.S'/\\') * ')')^-1
+ l.Cg('glue', 'id') * l.Cg('(\\' * (
'line' * l.Cc(1)
+ 'baseline' * l.Cc(2)
+ 'par' * l.Cc(3)
+ 'abovedisplay' * l.Cc(4)
+ 'belowdisplay' * l.Cc(5)
+ 'abovedisplayshort' * l.Cc(6)
+ 'belowdisplayshort' * l.Cc(7)
+ 'left' * l.Cc(8)
+ 'right' * l.Cc(9)
+ 'top' * l.Cc(10)
+ 'splittop' * l.Cc(11)
+ 'tab' * l.Cc(12)
+ 'space' * l.Cc(13)
+ 'xspace' * l.Cc(14)
+ 'parfill' * l.Cc(15)
+ 'math' * l.Cc(16)
+ 'thinmu' * l.Cc(17)
+ 'medmu' * l.Cc(18)
+ 'thickmu' * l.Cc(19)) * 'skip)' + l.Cc(0), 'subtype')
* ' ' * l.Cg(scaled, 'width')
* (' plus ' * l.Cg(scaled, 'stretch') * l.Cg(glue_order, 'stretch_order') + l.Cg(l.Cc(0), 'stretch') * l.Cg(l.Cc(0), 'stretch_order'))
* (' minus ' * l.Cg(scaled, 'shrink') * l.Cg(glue_order, 'shrink_order') + l.Cg(l.Cc(0), 'shrink') * l.Cg(l.Cc(0), 'shrink_order'))
+ l.Cg('penalty', 'id') * ' ' * l.Cg(int, 'penalty')
+ l.Cg('mark', 'id') * l.Cg('s' * int + l.Cc(0), 'class') * l.Cg(balanced_braces, 'mark')
)) * -1
local simple_noad = l.Ct('\\' * (
'math' * l.Cg(
'ord' * l.Cc(0)
+ 'open' * l.Cc(6)
+ 'op\\limits' * l.Cc(2)
+ 'op\\nolimits' * l.Cc(3)
+ 'op' * l.Cc(1)
+ 'bin' * l.Cc(4)
+ 'rel' * l.Cc(5)
+ 'close' * l.Cc(7)
+ 'punct' * l.Cc(8)
+ 'inner' * l.Cc(9)
+ 'under' * l.Cc(10)
+ 'over' * l.Cc(11)
+ 'vcenter' * l.Cc(12)
, 'subtype') * l.Cg(l.Cc'noad', 'id')
+ l.Cg('radical', 'id') * l.Cg(delimiter_code, 'left') * l.Cg(l.Cc(0), 'subtype')
+ l.Cg('accent', 'id') * l.Cg(math_char, 'accent') * l.Cg(l.Cc(0), 'subtype')
+ l.Cg('left' * l.Cc(1)
+ 'middle' * l.Cc(2)
+ 'right' * l.Cc(3), 'subtype') * l.Cg(delimiter_code, 'delim')
* l.Cg(l.Cc(0), 'options') * l.Cg(l.Cc(0), 'height')
* l.Cg(l.Cc(0), 'depth') * l.Cg(l.Cc(0), 'height')
* l.Cg(l.Cc(-1), 'class') * l.Cg(l.Cc'fence', 'id')
+ l.Cg(
'display' * l.Cc(0)
+ 'text' * l.Cc(2)
+ 'scriptscript' * l.Cc(6)
+ 'script' * l.Cc(4), 'subtype') * l.Cg('style', 'id')
+ 'm' * l.Cg('kern', 'id') * l.Cg(scaled, 'kern') * 'mu' * l.Cg(l.Cc(99), 'subtype')
+ l.Cg('glue', 'id') * (
'(\\nonscript)' * l.Cg(l.Cc(98), 'subtype')
+ '(\\mskip)' * l.Cg(l.Cc(99), 'subtype')
* ' ' * l.Cg(scaled, 'width') * 'mu'
* (' plus ' * l.Cg(scaled, 'stretch') * l.Cg(glue_order_mu, 'stretch_order') + l.Cg(l.Cc(0), 'stretch') * l.Cg(l.Cc(0), 'stretch_order'))
* (' minus ' * l.Cg(scaled, 'shrink') * l.Cg(glue_order_mu, 'shrink_order') + l.Cg(l.Cc(0), 'shrink') * l.Cg(l.Cc(0), 'shrink_order'))
)
)) * -1
+ generic_simple_node
local simple_text = l.Ct('\\' * (
l.Cg('math', 'id') * l.Cg(
'on' * l.Cc(0)
+ 'off' * l.Cc(1)
, 'subtype') * l.Cg(', surrounded ' * scaled + l.Cc(0), 'surround')
)) * -1
+ generic_simple_node
local box_node = l.Ct('\\' * l.Cg('h' * l.Cc'hlist'
+ 'v' * l.Cc'vlist') * 'box'
* hdw
* (', glue set ' * l.Cg('- ' * l.Cc(2) + l.Cc(1), 'glue_sign')
* l.Cg(scaled/function (s) return s/65536 end, 'glue_set')
* l.Cg(glue_order, 'glue_order')
+ l.Cg(l.Cc(0), 'glue_sign') * l.Cg(l.Cc(0), 'glue_set') * l.Cg(l.Cc(0), 'glue_order'))
* l.Cg(', shifted ' * scaled + l.Cc(0), 'shift')) * -1
local fraction_noad = l.Ct('\\fraction, thickness '
* l.Cg('= default' * l.Cc(0x40000000) + scaled, 'width')
* l.Cg(', left-delimiter ' * delimiter_code, 'left')^-1 * l.Cg(', right-delimiter ' * delimiter_code, 'right')^-1
* l.Cg(l.Cc'fraction', 'id'))
* -1
local mathchoice_noad = l.Ct('\\mathchoice' * l.Cg(l.Cc'choice', 'id') * -1)
local mark_whatsit = '\\write' * ('-' + l.R'09'^1) * '{LUAMML_MARK_REF:' * (l.R'09'^1/tonumber) * ':'
local parse_list
local function parse_kernel(lines, i, prefix, parsed)
local line = lines[i]
if not line or line:sub(1, #prefix) ~= prefix then return nil, i end
local result = math_char:match(lines[i], #prefix + 1)
if result then return result, i+1 end
if box_node:match(lines[i], #prefix + 1) then return skip_list(lines, i+1, prefix .. '.') end
result, i = parse_list(lines, i, prefix, parsed)
return {list = result, id = 'sub_mlist'}, i
end
function skip_list(lines, i, prefix)
i = i or 1
local count = #lines
while i <= count and lines[i]:sub(1, #prefix) == prefix do
i = i + 1
end
return {id = 'sub_box', list = {}}, i
end
function parse_list(lines, i, prefix, parsed)
i = i or 1
prefix = prefix or ''
local head, last
local mark_environment = {data = parsed,}
local current_mark, current_count, current_offset
while true do
local skip
local line = lines[i]
if not line or line:sub(1, #prefix) ~= prefix then break end
local simple = simple_noad:match(line, #prefix+1)
if simple then
simple.nucleus, i = parse_kernel(lines, i + 1, prefix .. '.', parsed)
simple.sup, i = parse_kernel(lines, i, prefix .. '^', parsed)
simple.sub, i = parse_kernel(lines, i, prefix .. '_', parsed)
if last then
simple.prev, last.next = last, simple
end
last = simple
else
local fraction = fraction_noad:match(line, #prefix+1)
if fraction then
fraction.num, i = parse_kernel(lines, i + 1, prefix .. '\\', parsed)
fraction.denom, i = parse_kernel(lines, i, prefix .. '/', parsed)
if last then
fraction.prev, last.next = last, fraction
end
last = fraction
else
local mathchoice = mathchoice_noad:match(line, #prefix+1)
if mathchoice then
mathchoice.display, i = parse_list(lines, i + 1, prefix .. 'D', parsed)
mathchoice.text, i = parse_list(lines, i, prefix .. 'T', parsed)
mathchoice.script, i = parse_list(lines, i, prefix .. 'S', parsed)
mathchoice.scriptscript, i = parse_list(lines, i, prefix .. 's', parsed)
if last then
mathchoice.prev, last.next = last, mathchoice
end
last = mathchoice
else
skip = true
local mark = mark_whatsit:match(line, #prefix+1)
if mark then
local mark_table = assert(load('return {' .. assert(parsed.marks[mark], 'Undefined mark encountered') .. '}', nil, 't', mark_environment))()
if current_mark then
if (mark_table.count or 1) > current_count then
error'Invalid mark nesting'
end
-- Ignore new mark if existing mark is evaluated. This should be replaced with proper nesting
else
current_mark, current_count = mark_table, mark_table.count or 1
current_offset = mark_table.offset or current_count
end
i = i + 1
else
print(line, prefix, i)
print('unknown noad ' .. line:sub(#prefix+1))
i = i + 1
end
end
end
end
if not head then head = last end
if not skip and current_mark then
current_count = current_count - 1
current_offset = current_offset - 1
if current_offset == 0 then
properties[current_mark.nucleus and last.nucleus or last] = {mathml_core = current_mark.core}
else
properties[last] = {mathml_core = false}
end
if current_count == 0 then current_mark = nil end
end
end
return head, i
end
return parse_list

View File

@ -1,96 +0,0 @@
#!/usr/bin/env texlua
require'pdfmml-emulate-node'
local convert = require'luamml-convert'
local mappings = require'luamml-legacy-mappings'
local to_xml = require'luamml-xmlwriter'
local parse_showlists = require'pdfmml-showlists'
local parse_log = require'pdfmml-logreader'
local text_families = {}
local attributes = lfs.attributes
local function try_extensions_(base, extension, ...)
if extension == nil then return end
local fullname = base .. extension
if attributes(fullname, 'mode') == 'file' then
return fullname
end
return try_extensions_(base, ...)
end
local function try_extensions(base, ...)
if attributes(base, 'mode') == 'file' then return base end
return try_extensions_(base, ...)
end
if #arg < 1 then
io.stderr:write(string.format('Usage: %s {logname} [{outname}]\n\z
If {outname} includes {}, then a separate file is written for every formula with {} replaced by the formula id.\n', arg[0]))
os.exit(1)
end
local parsed = assert(parse_log(assert(try_extensions(arg[1], '.tml', '.log'),
"Couldn't find input file.")))
for i, inst in ipairs(parsed.instructions) do
local _, _, family, mapping_name = inst:find'^REGISTER_MAPPING:([0-9]+):(.*)$'
if family then
local mapping = mappings[mapping_name]
if mapping then
convert.register_family(tonumber(family), mapping)
else
io.stderr:write(string.format('Unknown mapping %s ignored\n', mapping_name))
end
else
io.stderr:write'Unknown instruction ignored\n'
end
end
local out_prefix, out_suffix, out_stream
if not arg[2] or arg[2] == '-' then
out_stream = io.stdout
else
local _ _, _, out_prefix, out_suffix = arg[2]:find'^(.*){}(.*)$'
if not out_prefix then
out_stream = assert(io.open(arg[2], 'w'))
end
end
parsed.mathml = {}
local function shallow_copy(t)
local new = {}
for k, v in next, t do
new[k] = v
end
return new
end
-- Currently only 3 flag values are supported:
-- 0: Ignore (Doesn't make a lot of sense here)
-- 1: Only save
-- 3: Generate normally
for i, block in ipairs(parsed.groups) do
local flag, tag, label = block.flag, block.tag, block.label
block = block[1]
if flag & 3 ~= 0 then
local style = flag & 16 == 16 and flag>>5 & 0x7 or block.display and 0 or 2
local xml = convert.process(parse_showlists(block, nil, nil, parsed), style, text_families)
if flag & 2 == 2 then
local stream = out_stream or assert(io.open(out_prefix .. tostring(i) .. out_suffix, 'w'))
stream:write(to_xml(convert.make_root(shallow_copy(xml), style)), '\n')
if not out_stream then stream:close() end
end
if tag ~= 'mrow' then
if xml[0] == 'mrow' then
xml[0] = tag
else
xml = {[0] = tag, xml}
end
end
if (not block.display) and flag & 1 == 1 and label then
if parsed.mathml[label] then
error'Invalid label reuse'
end
parsed.mathml[label] = xml
end
end
end

View File

@ -1,98 +0,0 @@
% \newcommand\Luamml{\pkg{Luamml}}
% \newcommand\luamml{\pkg{luamml}}
% \newcommand\xmltag[1]{\texttt{<#1>}}
% \section{\Luamml's representation of XML and MathML}
% In the following I assume basic familiarity with both Lua\TeX's representation of math noads and MathML.
%
% \subsection{Representation of XML elements}
% In many places, \luamml\ passes around XML elements. Every element is represented by a Lua table.
% Element \texttt 0 must always be present and is a string representing the tag name.
% The positive integer elements of the table represent child elements (either strings for direct text content or nested tables for nested elements).
% All string members which do not start with a colon are attributes, whose value is the result of applying \texttt{tostring} to the field value.
% This implies that these values should almost always be strings, except that the value \texttt 0 (since it never needs a unit) can often be set as a number.
% For example the XML document
% \begin{verbatim}
% <math block="display">
% <mn>0</mn>
% <mo> &lt; </mo>
% <mi mathvariant="normal">x</mi>
% </math>
% \end{verbatim}
% would be represented by the Lua table
% \begin{verbatim}
% {[0] = "math", block="display",
% {[0] = "mn", "0"},
% {[0] = "mo", "<"},
% {[0] = "mi", mathvariant="normal", "x"}
% }
% \end{verbatim}
%
% \subsection{Expression cores}
% MathML knows the concept of \enquote{embellished operators}:
% \begin{blockquote}
% The precise definition of an \enquote{embellished operator} is:
% \begin{itemize}
% \item an \xmltag{mo} element;
% \item or one of the elements \xmltag{msub}, \xmltag{msup}, \xmltag{msubsup}, \xmltag{munder}, \xmltag{mover}, \xmltag{munderover}, \xmltag{mmultiscripts}, \xmltag{mfrac}, or \xmltag{semantics} (§ 5.1 Annotation Framework), whose first argument exists and is an embellished operator;
% \item or one of the elements \xmltag{mstyle}, \xmltag{mphantom}, or \xmltag{mpadded}, such that an mrow containing the same arguments would be an embellished operator;
% \item or an \xmltag{maction} element whose selected sub-expression exists and is an embellished operator;
% \item or an \xmltag{mrow} whose arguments consist (in any order) of one embellished operator and zero or more space-like elements.
% \end{itemize}
% \end{blockquote}
% For every embellished operator, MathML calls the \xmltag{mo} element defining the embellished operator the \enquote{core} of the embellished operator.
%
% \Luamml\ makes this slightly more general: Every expression is represented by a pair of two elements: The expression and it's core.
% The core is always a \xmltag{mo}, \xmltag{mi}, or \xmltag{mn}, \texttt{nil} or s special marker for space like elements.
%
% If and only if the element is a embellished operator the core is a \xmltag{mo} element representing the core of the embellished operator.
% The core is a \xmltag{mi} or a \xmltag{mn} element if and only if the element would be an embellished operator with this core if this element where a \xmltag{mo} element.
% The core is the special space like marker for space like elements. Otherwise the core is \texttt{nil}.
%
% \subsection{Translation of math noads}
% A math lists can contain the following node types: noad, fence, fraction, radical, accent, style, choice, ins, mark, adjust, boundary, whatsit, penalty, disc, glue, and kern. The \enquote{noads}
%
% \subsubsection{Translation of kernel noads}
% The math noads of this list contain nested kernel noads. So in the first step, we look into how kernel nodes are translated to math nodes.
%
% \paragraph{\texttt{math_char} kernel noads}
% First the family and character value in the \texttt{math_char} are used to lookup the Unicode character value of this \texttt{math_char}.
% (For \texttt{unicode-math}, this is usually just the character value. Legacy maths has to be remapped based on the family.)
% Then there are two cases: The digits \texttt{0} to \texttt{9} are mapped to \xmltag{mn} elements, everything else becomes a \xmltag{mi} element with \texttt{mathvariant} set to \texttt{normal}.
% (The \texttt{mathvariant} value might get suppressed if the character defaults to mathvariant \texttt{normal}.)
% In either case, the \texttt{tex:family} attribute is set to the family number if it's not \texttt{0}.
%
% The core is always set to the expression itself. E.g.\ the \texttt{math_char} kernel noad \verb+\fam3 a+ would become (assuming no remapping for this family)
% \begin{verbatim}
% {[0] = 'mi',
% mathvariant = 'normal',
% ["tex:family"] = 3,
% "a"
% }
% \end{verbatim}
%
% \subsubsection{\texttt{sub_box} kernel noads}
% I am open to suggestions how to convert them properly.
%
% \subsubsection{\texttt{sub_mlist} kernel noads}
% The inner list is converted as a \xmltag{mrow} element, with the core being the core of the \xmltag{mrow} element. See the rules for this later.
%
% \subsubsection{\texttt{delim} kernel noads}
% If the \texttt{small_char} is zero, these get converted as space like elements of the form
% \begin{verbatim}
% {[0] = 'mspace',
% width = '1.196pt',
% }
% \end{verbatim}
% where 1.196 is replaced by the current value of \verb+\nulldelimiterspace+ converted to \texttt{bp}.
%
% Otherwise the same rules as for \texttt{math_char} apply,
% except that instead of \texttt{mi} or \xmltag{mn} elements,
% \texttt{mo} elements are generated,
% \texttt{mathvariant} is never set,
% \texttt{stretchy} is set to \texttt{true} if the operator is not on the list of default stretchy operators in the MathML specification
% nd \texttt{lspace} and \texttt{rspace} attributes are set to zero.
%
% \subsubsection{\texttt{acc} kernel noads}
% Depending on the surrounding element containing the \texttt{acc} kernel noad, it is either stretchy or not.
% If it's stretchy, the same rules as for \texttt{delim} apply, except that \texttt{lspace} and \texttt{rspace} are not set.
% Otherwise the \texttt{stretchy} attribute is set to false if the operator is on the list of default stretchy operators.

46
test_tex.tex Normal file
View File

@ -0,0 +1,46 @@
\documentclass{article}
\usepackage{luamml}
\usepackage{amsmath,array}
\usepackage{unicode-math}
%% Uncomment the following lines when used without unicode-math
% \RegisterFamilyMapping\symsymbols{oms}
% \RegisterFamilyMapping\symletters{oml}
% \RegisterFamilyMapping\symlargesymbols{omx}
\ExplSyntaxOn
\tracingmathml=2
\pdfvariable compresslevel=0
\cs_new_protected:Npn \ShowMathMLObj {
\message { \luamml_get_last_mathml_stream:e{}~0~R }
}
\ExplSyntaxOff
\begin{document}
\[
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
=
\begin{cases}
1 & $if $a=b\\
2 & $else$
\end{cases}
\]
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
\]
\[
\sum_a\underline c\dot bc'
\]
\begin{align}
abc&=def & e^{\mathrm{i}\pi}&=-1\\
1+2&=3\\
5
\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0$.
\end{document}

View File

@ -1,142 +0,0 @@
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑎</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mi>𝑏</mi>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mo fence="true" lspace="0" rspace="0" symmetric="true">(</mo>
<mspace width="-4.981pt" />
<mpadded lspace="+4.981pt" width="+9.963pt">
<mtable>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtable>
</mpadded>
<mspace width="-4.981pt" />
<mo fence="true" lspace="0" rspace="0" symmetric="true">)</mo>
</mrow>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mrow>
<mo fence="true" lspace="0" rspace="0" symmetric="true">{</mo>
<mpadded lspace="+4.981pt" width="+9.963pt">
<mtable>
<mtr>
<mtd columnalign="left">
<mn>1</mn>
</mtd>
<mtd columnalign="left">
<mtext>if&#160;
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑎</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mi>𝑏</mi>
</math></mtext>
</mtd>
</mtr>
<mtr>
<mtd columnalign="left">
<mn>2</mn>
</mtd>
<mtd columnalign="left">
<mtext>else</mtext>
</mtd>
</mtr>
</mtable>
</mpadded>
<mspace width="1.196pt" />
</mrow>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑥</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mfrac>
<mrow>
<mo lspace="0" rspace="0.222em"></mo>
<mi>𝑏</mi>
<mo lspace="0.222em" rspace="0.222em">±</mo>
<msqrt>
<mrow>
<msup>
<mi>𝑏</mi>
<mn>2</mn>
</msup>
<mo lspace="0.222em" rspace="0.222em"></mo>
<mn>4</mn>
<mi>𝑎</mi>
<mi>𝑐</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>𝑎</mi>
</mrow>
</mfrac>
<mo lspace="0" rspace="0">.</mo>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<munder>
<mo lspace="0" movablelimits="true" rspace="0.167em">∑</mo>
<mi>𝑎</mi>
</munder>
<munder>
<mi>𝑐</mi>
<mo>_</mo>
</munder>
<mover>
<mi>𝑏</mi>
<mo stretchy="true">.</mo>
</mover>
<msup>
<mi>𝑐</mi>
<mi mathvariant="normal"></mi>
</msup>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi mathvariant="normal">sin</mi>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.222em" rspace="0.222em"></mo>
<mi mathvariant="normal">sin</mi>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0.222em" rspace="0.222em">+</mo>
<mn>2</mn>
<mi>𝜋</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mn>0</mn>
</math>

View File

@ -1,44 +0,0 @@
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
testphase = {phase-III,table,math},
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
\begin{document}
\ExplSyntaxOn
\luamml_set_filename:n {
\jobname .mml
}
\luamml_process:
\luamml_begin_single_file:
\ExplSyntaxOff
\[
\left(\begin{matrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{matrix}\right)
=
\begin{cases}
1 & \mbox{if $a=b$}\\
2 & \mbox{else}
\end{cases}
\]
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
\]
\[
\sum_a\underline c\dot bc'
\]
Es gilt $\sin(x)-\sin(x+2\pi)=0$.
\ExplSyntaxOn
\luamml_end_single_file:
\ExplSyntaxOff
\end{document}

View File

@ -1,33 +0,0 @@
<math xmlns="http://www.w3.org/1998/Math/MathML">
<msqrt>
<mi>𝑥</mi>
</msqrt>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<msqrt>
<msqrt>
<mi>𝑥</mi>
</msqrt>
</msqrt>
<mo lspace="0.222em" rspace="0.222em">+</mo>
<mn>2</mn>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑥</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<msqrt>
<mroot>
<msup>
<mi>𝑦</mi>
<mn>2</mn>
</msup>
<mn>3</mn>
</mroot>
</msqrt>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mroot>
<mi>𝑦</mi>
<mn>3</mn>
</mroot>
</math>

View File

@ -1,28 +0,0 @@
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
testphase = {phase-III,table,math},
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
\begin{document}
\ExplSyntaxOn
\luamml_set_filename:n {
\jobname .mml
}
\luamml_process:
\luamml_begin_single_file:
\ExplSyntaxOff
$ \sqrt{x} $
$ \sqrt{\sqrt{x}} + 2 $
$ x = \sqrt{\sqrt[3]{y^2}} $
$\sqrt[3]{y}$
\end{document}

View File

@ -1,22 +0,0 @@
\ExplSyntaxOn
\sys_gset_rand_seed:n{42}
\ExplSyntaxOff
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
testphase = {phase-III,math,table},
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
\tagpdfsetup{math/mathml/structelem,attach-css=false}
\begin{document}
$ \sqrt{x} $
$ \sqrt{\sqrt{x}} + 2 $
$ x = \sqrt{\sqrt[3]{y^2}} $
$\sqrt[3]{y}$
\end{document}

View File

@ -1,990 +0,0 @@
%PDF-2.0
%ÌÕÁÔÅØÐÄÆ
22 0 obj
<< /Type /EmbeddedFile /Subtype /application#2Fmathml+xml /Params<</ModDate (D:20160520) >> /Length 88 >>
stream
<math xmlns="http://www.w3.org/1998/Math/MathML"> <msqrt> <mi>ð<>¥</mi> </msqrt> </math>
endstream
endobj
23 0 obj
<< /Type /Filespec /AFRelationship /Supplement /Desc (mathml-1) /F (mathml-1.xml) /UF <FEFF006D006100740068006D006C002D0031002E0078006D006C> /EF<</F 22 0 R/UF 22 0 R>> >>
endobj
24 0 obj
<< /Type /EmbeddedFile /Subtype /application#2Fmathml+xml /Params<</ModDate (D:20160520) >> /Length 161 >>
stream
<math xmlns="http://www.w3.org/1998/Math/MathML"> <msqrt> <msqrt> <mi>ð<>¥</mi> </msqrt> </msqrt> <mo lspace="0.222em" rspace="0.222em">+</mo> <mn>2</mn> </math>
endstream
endobj
25 0 obj
<< /Type /Filespec /AFRelationship /Supplement /Desc (mathml-2) /F (mathml-2.xml) /UF <FEFF006D006100740068006D006C002D0032002E0078006D006C> /EF<</F 24 0 R/UF 24 0 R>> >>
endobj
26 0 obj
<< /Type /EmbeddedFile /Subtype /application#2Fmathml+xml /Params<</ModDate (D:20160520) >> /Length 201 >>
stream
<math xmlns="http://www.w3.org/1998/Math/MathML"> <mi>ð<>¥</mi> <mo lspace="0.278em" rspace="0.278em">=</mo> <msqrt> <mroot> <msup> <mi>ð<>¦</mi> <mn>2</mn> </msup> <mn>3</mn> </mroot> </msqrt> </math>
endstream
endobj
27 0 obj
<< /Type /Filespec /AFRelationship /Supplement /Desc (mathml-3) /F (mathml-3.xml) /UF <FEFF006D006100740068006D006C002D0033002E0078006D006C> /EF<</F 26 0 R/UF 26 0 R>> >>
endobj
28 0 obj
<< /Type /EmbeddedFile /Subtype /application#2Fmathml+xml /Params<</ModDate (D:20160520) >> /Length 99 >>
stream
<math xmlns="http://www.w3.org/1998/Math/MathML"> <mroot> <mi>ð<>¦</mi> <mn>3</mn> </mroot> </math>
endstream
endobj
29 0 obj
<< /Type /Filespec /AFRelationship /Supplement /Desc (mathml-4) /F (mathml-4.xml) /UF <FEFF006D006100740068006D006C002D0034002E0078006D006C> /EF<</F 28 0 R/UF 28 0 R>> >>
endobj
35 0 obj
<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 11 >>
stream
$\sqrt {x}$
endstream
endobj
36 0 obj
<< /Type /Filespec /AFRelationship /Source /Desc (TeX source) /F (tag-AFfile1.tex) /UF <FEFF007400610067002D0041004600660069006C00650031002E007400650078> /EF<</F 35 0 R/UF 35 0 R>> >>
endobj
43 0 obj
<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 23 >>
stream
$\sqrt {\sqrt {x}} + 2$
endstream
endobj
44 0 obj
<< /Type /Filespec /AFRelationship /Source /Desc (TeX source) /F (tag-AFfile2.tex) /UF <FEFF007400610067002D0041004600660069006C00650032002E007400650078> /EF<</F 43 0 R/UF 43 0 R>> >>
endobj
50 0 obj
<< /O/NSO/NS 13 0 R/lspace(0.222em)/rspace(0.222em) >>
endobj
55 0 obj
<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 28 >>
stream
$x = \sqrt {\sqrt [3]{y^2}}$
endstream
endobj
56 0 obj
<< /Type /Filespec /AFRelationship /Source /Desc (TeX source) /F (tag-AFfile3.tex) /UF <FEFF007400610067002D0041004600660069006C00650033002E007400650078> /EF<</F 55 0 R/UF 55 0 R>> >>
endobj
60 0 obj
<< /O/NSO/NS 13 0 R/lspace(0.278em)/rspace(0.278em) >>
endobj
70 0 obj
<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 14 >>
stream
$\sqrt [3]{y}$
endstream
endobj
71 0 obj
<< /Type /Filespec /AFRelationship /Source /Desc (TeX source) /F (tag-AFfile4.tex) /UF <FEFF007400610067002D0041004600660069006C00650034002E007400650078> /EF<</F 70 0 R/UF 70 0 R>> >>
endobj
76 0 obj
<< /Type /Metadata /Subtype /XML /Length 11691 >>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"
xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"
xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"
xmlns:pdfxid="http://www.npes.org/pdfx/ns/id/"
xmlns:prism="http://prismstandard.org/namespaces/basic/3.0/"
xmlns:stFnt="http://ns.adobe.com/xap/1.0/sType/Font#"
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#"
xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type#"
xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field#">
<pdfaExtension:schemas>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>
<pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>OriginalDocumentID</pdfaProperty:name>
<pdfaProperty:valueType>URI</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>The common identifier for all versions and renditions of a document.</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/A Identification Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>year</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Year of standard</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>rev</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Revision year of standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/UA Universal Accessibility Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfuaid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.aiim.org/pdfua/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>part</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Part of ISO 14289 standard</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>rev</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Revision of ISO 14289 standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/X ID Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfxid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.npes.org/pdfx/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>GTS_PDFXVersion</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>ID of PDF/X standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PRISM Basic Metadata</pdfaSchema:schema>
<pdfaSchema:prefix>prism</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://prismstandard.org/namespaces/basic/3.0/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>complianceProfile</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>PRISM specification compliance profile to which this document adheres</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>publicationName</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication name</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>aggregationType</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication type</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>bookEdition</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Edition of the book in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>volume</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication volume number</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>number</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication issue number within a volume</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>pageRange</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Page range for the document within the print version of its publication</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>issn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISSN for the printed publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>eIssn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISSN for the electronic publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>isbn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISBN for the publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>doi</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Digital Object Identifier for the document</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>url</pdfaProperty:name>
<pdfaProperty:valueType>URL</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>URL at which the document can be found</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>byteCount</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Approximate file size in octets</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>pageCount</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Number of pages in the print version of the document</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>subtitle</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Document's subtitle</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
</rdf:Bag>
</pdfaExtension:schemas>
<pdf:Producer>luahbtex-NN.NN.NN</pdf:Producer>
<pdf:PDFVersion>2.0</pdf:PDFVersion>
<dc:type>
<rdf:Bag>
<rdf:li>Text</rdf:li>
</rdf:Bag>
</dc:type>
<dc:language>
<rdf:Bag>
<rdf:li>en</rdf:li>
</rdf:Bag>
</dc:language>
<dc:date>
<rdf:Seq>
<rdf:li>2016-05-20T09:00:00Z</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>test_sqrt.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
<xmp:CreateDate>2016-05-20T09:00:00Z</xmp:CreateDate>
<xmp:ModifyDate>2016-05-20T09:00:00Z</xmp:ModifyDate>
<xmp:MetadataDate>2016-05-20T09:00:00Z</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:d1433a12-c113-44c0-8c00-afe828e37deb</xmpMM:DocumentID>
<xmpMM:InstanceID>uuid:0a57c455-157a-4141-8c19-6237d832fc80</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
endstream
endobj
79 0 obj
<< /Length 2081 >>
stream
/opacity1 gs
/Artifact BMC
EMC
/Formula<</MCID 0>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 148.712 664.413 Tm [<0C05>]TJ
ET
q
1 0 0 1 157.011 664.613 cm
[] 0 d 0 J 0.398 w 0 0 m 5.699 0 l S
Q
EMC
/mi<</MCID 1>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 157.011 657.235 Tm [<0527>]TJ
ET
EMC
/Artifact BMC
EMC
/Formula<</MCID 2>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 148.712 644.986 Tm [<0C09>]TJ
ET
q
1 0 0 1 158.675 653.255 cm
[] 0 d 0 J 0.398 w 0 0 m 13.998 0 l S
Q
BT
/F20 9.96264 Tf
1 0 0 1 158.675 651.412 Tm [<0C05>]TJ
ET
q
1 0 0 1 166.974 651.611 cm
[] 0 d 0 J 0.398 w 0 0 m 5.699 0 l S
Q
EMC
/mi<</MCID 3>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 166.974 644.234 Tm [<0527>]TJ
ET
EMC
/mo<</MCID 4>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 174.886 644.234 Tm [<000C>]TJ
ET
EMC
/mn<</MCID 5>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 184.851 644.234 Tm [<0013>]TJ
ET
EMC
/Artifact BMC
EMC
/Formula<</MCID 6>> BDC
EMC
/mi<</MCID 7>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 148.712 627.309 Tm [<0527>]TJ
ET
EMC
/mo<</MCID 8>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 157.178 627.309 Tm [<001E>]TJ
ET
EMC
/Formula<</MCID 9>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 167.697 628.648 Tm [<0C0A>]TJ
ET
q
1 0 0 1 177.659 639.905 cm
[] 0 d 0 J 0.398 w 0 0 m 20.272 0 l S
Q
EMC
/mn<</MCID 10>> BDC
BT
/F22 4.98132 Tf
1 0 0 1 180.429 631.686 Tm [<0258>]TJ
ET
EMC
/Formula<</MCID 11>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 178.282 628 Tm [<0C09>]TJ
ET
q
1 0 0 1 188.244 636.269 cm
[] 0 d 0 J 0.398 w 0 0 m 9.687 0 l S
Q
EMC
/mi<</MCID 12>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 188.244 627.309 Tm [<0528>]TJ
ET
EMC
/mn<</MCID 13>> BDC
BT
/F21 6.97385 Tf
1 0 0 1 193.405 630.188 Tm [<03F5>]TJ
ET
EMC
/Artifact BMC
EMC
/Formula<</MCID 14>> BDC
EMC
/mn<</MCID 15>> BDC
BT
/F22 4.98132 Tf
1 0 0 1 151.482 616.792 Tm [<0258>]TJ
ET
EMC
/Formula<</MCID 16>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 149.335 620.379 Tm [<0C05>]TJ
ET
q
1 0 0 1 157.634 620.578 cm
[] 0 d 0 J 0.398 w 0 0 m 4.882 0 l S
Q
EMC
/mi<</MCID 17>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 157.634 614.167 Tm [<0528>]TJ
ET
EMC
/Artifact BMC
EMC
/Artifact BMC
BT
/F15 9.96264 Tf
1 0 0 1 303.133 89.365 Tm [<0052>]TJ
ET
EMC
/Artifact BMC
EMC
endstream
endobj
78 0 obj
<< /Type /Page /Contents 79 0 R /Resources 77 0 R /MediaBox [ 0 0 612 792 ] /StructParents 0/Tabs /S /Parent 84 0 R >>
endobj
77 0 obj
<< /ExtGState 1 0 R /Font << /F20 80 0 R /F22 81 0 R /F21 82 0 R /F15 83 0 R >> >>
endobj
1 0 obj
<< /opacity1 <</ca 1/CA 1>> >>
endobj
85 0 obj
<< /Marked true >>
endobj
86 0 obj
<< /Names[(l3ef0001) 23 0 R (l3ef0002) 25 0 R (l3ef0003) 27 0 R (l3ef0004) 29 0 R] >>
endobj
6 0 obj
<< /Nums [0 [ 34 0 R 39 0 R 42 0 R 48 0 R 49 0 R 51 0 R 54 0 R 58 0 R 59 0 R 54 0 R 66 0 R 54 0 R 64 0 R 65 0 R 69 0 R 75 0 R 69 0 R 74 0 R]
] >>
endobj
87 0 obj
<< /Limits [(ID.002) (ID.038)]/Names [(ID.002) 21 0 R (ID.003) 30 0 R (ID.004) 31 0 R (ID.005) 32 0 R (ID.006) 33 0 R (ID.007) 34 0 R (ID.008) 37 0 R (ID.009) 38 0 R (ID.010) 39 0 R (ID.011) 40 0 R (ID.012) 41 0 R (ID.013) 42 0 R (ID.014) 45 0 R (ID.015) 46 0 R (ID.016) 47 0 R (ID.017) 48 0 R (ID.018) 49 0 R (ID.019) 51 0 R (ID.020) 52 0 R (ID.021) 53 0 R (ID.022) 54 0 R (ID.023) 57 0 R (ID.024) 58 0 R (ID.025) 59 0 R (ID.026) 61 0 R (ID.027) 62 0 R (ID.028) 63 0 R (ID.029) 64 0 R (ID.030) 65 0 R (ID.031) 66 0 R (ID.032) 67 0 R (ID.033) 68 0 R (ID.034) 69 0 R (ID.035) 72 0 R (ID.036) 73 0 R (ID.037) 74 0 R (ID.038) 75 0 R ] >>
endobj
88 0 obj
<< /Kids [87 0 R] >>
endobj
7 0 obj
<< /Artifact /NonStruct /DocumentFragment /Art /Aside /Note /H7 /H6 /H8 /H6 /H9 /H6 /H10 /H6 /Title /P /FENote /Note /Sub /Span /Em /Span /Strong /Span /title /P /part /P /section /H1 /subsection /H2 /subsubsection /H3 /paragraph /H4 /subparagraph /H5 /list /L /itemize /L /enumerate /L /description /L /quote /BlockQuote /quotation /BlockQuote /verbatim /P /item /LI /itemlabel /Lbl /itembody /LBody /footnote /Note /footnotemark /Lbl /footnotelabel /Lbl /text-unit /Part /text /P /theorem-like /Sect /codeline /Span /float /Note /figures /Sect /tables /Sect >>
endobj
89 0 obj
<< /justify <</O/Layout/TextAlign/Justify>>
/inline <</O/Layout/Placement/Inline>>
/TH-both <</O/Table/Scope/Both>>
/TH-row <</O/Table/Scope/Row>>
/TH-col <</O/Table/Scope/Column>>
>>
endobj
9 0 obj
<< /Type /Namespace /NS (http://iso.org/pdf/ssn) >>
endobj
11 0 obj
<< /Type /Namespace /NS (http://iso.org/pdf2/ssn) >>
endobj
13 0 obj
<< /Type /Namespace /NS (http://www.w3.org/1998/Math/MathML) >>
endobj
16 0 obj
<< /title [/Title 11 0 R] /part [/Title 11 0 R] /section [/H1 11 0 R] /subsection [/H2 11 0 R] /subsubsection [/H3 11 0 R] /paragraph [/H4 11 0 R] /subparagraph [/H5 11 0 R] /list [/L 11 0 R] /itemize [/L 11 0 R] /enumerate [/L 11 0 R] /description [/L 11 0 R] /quote [/BlockQuote 9 0 R] /quotation [/BlockQuote 9 0 R] /verbatim [/P 11 0 R] /item [/LI 11 0 R] /itemlabel [/Lbl 11 0 R] /itembody [/LBody 11 0 R] /footnote [/FENote 11 0 R] /footnotemark [/Lbl 11 0 R] /footnotelabel [/Lbl 11 0 R] /text-unit [/Part 11 0 R] /text [/P 11 0 R] /theorem-like [/Sect 11 0 R] /codeline [/Sub 11 0 R] /float [/Aside 11 0 R] /figures [/Sect 11 0 R] /tables [/Sect 11 0 R] >>
endobj
15 0 obj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/dflt) /RoleMapNS 16 0 R >>
endobj
18 0 obj
<< /chapter [/H1 11 0 R] /section [/H2 11 0 R] /subsection [/H3 11 0 R] /subsubsection [/H4 11 0 R] /paragraph [/H5 11 0 R] /subparagraph [/H6 11 0 R] >>
endobj
17 0 obj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/book) /RoleMapNS 18 0 R >>
endobj
19 0 obj
<< /Type /Namespace /NS (data:,C9B55C18-275C-494E-C10F-E4B83CD03F23) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R ]
endobj
21 0 obj
<< /Type /StructElem /S /Document /NS 11 0 R /P 5 0 R /K [32 0 R 40 0 R 52 0 R 67 0 R] /ID (ID.002) >>
endobj
30 0 obj
<< /Type /StructElem /S /Artifact /NS 15 0 R /P 5 0 R /ID (ID.003) >>
endobj
31 0 obj
<< /Type /StructElem /S /Artifact /NS 15 0 R /P 5 0 R /ID (ID.004) >>
endobj
32 0 obj
<< /Type /StructElem /S /text-unit /NS 15 0 R /P 21 0 R /K 33 0 R /ID (ID.005) >>
endobj
33 0 obj
<< /Type /StructElem /C /justify /S /text /NS 15 0 R /P 32 0 R /K [ 34 0 R ] /ID (ID.006) >>
endobj
34 0 obj
<< /Type /StructElem /C /inline /AF [23 0 R 36 0 R] /T <FEFF006D006100740068> /S /Formula /NS 11 0 R /P 33 0 R /K [<</Type /MCR /Pg 78 0 R /MCID 0>> 37 0 R] /ID (ID.007) >>
endobj
37 0 obj
<< /Type /StructElem /S /math /NS 13 0 R /P 34 0 R /K 38 0 R /ID (ID.008) >>
endobj
38 0 obj
<< /Type /StructElem /S /msqrt /NS 13 0 R /P 37 0 R /K 39 0 R /ID (ID.009) >>
endobj
39 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 38 0 R /K <</Type /MCR /Pg 78 0 R /MCID 1>> /ID (ID.010) >>
endobj
40 0 obj
<< /Type /StructElem /S /text-unit /NS 15 0 R /P 21 0 R /K 41 0 R /ID (ID.011) >>
endobj
41 0 obj
<< /Type /StructElem /C /justify /S /text /NS 15 0 R /P 40 0 R /K [ 42 0 R ] /ID (ID.012) >>
endobj
42 0 obj
<< /Type /StructElem /C /inline /AF [25 0 R 44 0 R] /T <FEFF006D006100740068> /S /Formula /NS 11 0 R /P 41 0 R /K [<</Type /MCR /Pg 78 0 R /MCID 2>> 45 0 R] /ID (ID.013) >>
endobj
45 0 obj
<< /Type /StructElem /S /math /NS 13 0 R /P 42 0 R /K [46 0 R 49 0 R 51 0 R] /ID (ID.014) >>
endobj
46 0 obj
<< /Type /StructElem /S /msqrt /NS 13 0 R /P 45 0 R /K 47 0 R /ID (ID.015) >>
endobj
47 0 obj
<< /Type /StructElem /S /msqrt /NS 13 0 R /P 46 0 R /K 48 0 R /ID (ID.016) >>
endobj
48 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 47 0 R /K <</Type /MCR /Pg 78 0 R /MCID 3>> /ID (ID.017) >>
endobj
49 0 obj
<< /Type /StructElem /A 50 0 R /S /mo /NS 13 0 R /P 45 0 R /K <</Type /MCR /Pg 78 0 R /MCID 4>> /ID (ID.018) >>
endobj
51 0 obj
<< /Type /StructElem /S /mn /NS 13 0 R /P 45 0 R /K <</Type /MCR /Pg 78 0 R /MCID 5>> /ID (ID.019) >>
endobj
52 0 obj
<< /Type /StructElem /S /text-unit /NS 15 0 R /P 21 0 R /K 53 0 R /ID (ID.020) >>
endobj
53 0 obj
<< /Type /StructElem /C /justify /S /text /NS 15 0 R /P 52 0 R /K [ 54 0 R ] /ID (ID.021) >>
endobj
54 0 obj
<< /Type /StructElem /C /inline /AF [27 0 R 56 0 R] /T <FEFF006D006100740068> /S /Formula /NS 11 0 R /P 53 0 R /K [<</Type /MCR /Pg 78 0 R /MCID 6>> <</Type /MCR /Pg 78 0 R /MCID 9>> <</Type /MCR /Pg 78 0 R /MCID 11>> 57 0 R] /ID (ID.022) >>
endobj
57 0 obj
<< /Type /StructElem /S /math /NS 13 0 R /P 54 0 R /K [58 0 R 59 0 R 61 0 R] /ID (ID.023) >>
endobj
58 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 57 0 R /K <</Type /MCR /Pg 78 0 R /MCID 7>> /ID (ID.024) >>
endobj
59 0 obj
<< /Type /StructElem /A 60 0 R /S /mo /NS 13 0 R /P 57 0 R /K <</Type /MCR /Pg 78 0 R /MCID 8>> /ID (ID.025) >>
endobj
61 0 obj
<< /Type /StructElem /S /msqrt /NS 13 0 R /P 57 0 R /K 62 0 R /ID (ID.026) >>
endobj
62 0 obj
<< /Type /StructElem /S /mroot /NS 13 0 R /P 61 0 R /K [63 0 R 66 0 R] /ID (ID.027) >>
endobj
63 0 obj
<< /Type /StructElem /S /msup /NS 13 0 R /P 62 0 R /K [64 0 R 65 0 R] /ID (ID.028) >>
endobj
64 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 63 0 R /K <</Type /MCR /Pg 78 0 R /MCID 12>> /ID (ID.029) >>
endobj
65 0 obj
<< /Type /StructElem /S /mn /NS 13 0 R /P 63 0 R /K <</Type /MCR /Pg 78 0 R /MCID 13>> /ID (ID.030) >>
endobj
66 0 obj
<< /Type /StructElem /S /mn /NS 13 0 R /P 62 0 R /K <</Type /MCR /Pg 78 0 R /MCID 10>> /ID (ID.031) >>
endobj
67 0 obj
<< /Type /StructElem /S /text-unit /NS 15 0 R /P 21 0 R /K 68 0 R /ID (ID.032) >>
endobj
68 0 obj
<< /Type /StructElem /C /justify /S /text /NS 15 0 R /P 67 0 R /K [ 69 0 R ] /ID (ID.033) >>
endobj
69 0 obj
<< /Type /StructElem /C /inline /AF [29 0 R 71 0 R] /T <FEFF006D006100740068> /S /Formula /NS 11 0 R /P 68 0 R /K [<</Type /MCR /Pg 78 0 R /MCID 14>> <</Type /MCR /Pg 78 0 R /MCID 16>> 72 0 R] /ID (ID.034) >>
endobj
72 0 obj
<< /Type /StructElem /S /math /NS 13 0 R /P 69 0 R /K 73 0 R /ID (ID.035) >>
endobj
73 0 obj
<< /Type /StructElem /S /mroot /NS 13 0 R /P 72 0 R /K [74 0 R 75 0 R] /ID (ID.036) >>
endobj
74 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 73 0 R /K <</Type /MCR /Pg 78 0 R /MCID 17>> /ID (ID.037) >>
endobj
75 0 obj
<< /Type /StructElem /S /mn /NS 13 0 R /P 73 0 R /K <</Type /MCR /Pg 78 0 R /MCID 15>> /ID (ID.038) >>
endobj
5 0 obj
<< /Type /StructTreeRoot /Namespaces 8 0 R /IDTree 88 0 R /ClassMap 89 0 R /ParentTree 6 0 R /RoleMap 7 0 R /K 21 0 R >>
endobj
90 0 obj
[ 82 [ 500 ] ]
endobj
92 0 obj
<< /Subtype /CIDFontType0C /Length 574 >>
[BINARY STREAM]
endobj
91 0 obj
<< /Type /FontDescriptor /FontName /JFRMQG+LMRoman10-Regular /Flags 4 /FontBBox [ -430 -290 1417 1127 ] /Ascent 1127 /CapHeight 683 /Descent -290 /ItalicAngle 0 /StemV 93 /XHeight 431 /FontFile3 92 0 R >>
endobj
93 0 obj
<< /Length 692 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-JFRMQG-LMRoman10-Regular-0)
%%Title: (TeX-JFRMQG-LMRoman10-Regular-0 TeX JFRMQG-LMRoman10-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (JFRMQG-LMRoman10-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-JFRMQG-LMRoman10-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
1 beginbfchar
<0052> <0031>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
83 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /JFRMQG+LMRoman10-Regular /DescendantFonts [ 94 0 R ] /ToUnicode 93 0 R >>
endobj
94 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /JFRMQG+LMRoman10-Regular /FontDescriptor 91 0 R /W 90 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
95 0 obj
[ 1013 [ 569 ] ]
endobj
97 0 obj
<< /Subtype /CIDFontType0C /Length 702 >>
[BINARY STREAM]
endobj
96 0 obj
<< /Type /FontDescriptor /FontName /MGWLKY+LatinModernMath-Regular /Flags 4 /FontBBox [ -1042 -3060 4082 3560 ] /Ascent 806 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 113 /XHeight 431 /FontFile3 97 0 R >>
endobj
98 0 obj
<< /Length 722 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-MGWLKY-LatinModernMath-Regular-0)
%%Title: (TeX-MGWLKY-LatinModernMath-Regular-0 TeX MGWLKY-LatinModernMath-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (MGWLKY-LatinModernMath-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-MGWLKY-LatinModernMath-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
1 beginbfchar
<03F5> <0032>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
82 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /MGWLKY+LatinModernMath-Regular /DescendantFonts [ 99 0 R ] /ToUnicode 98 0 R >>
endobj
99 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /MGWLKY+LatinModernMath-Regular /FontDescriptor 96 0 R /W 95 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
100 0 obj
[ 600 [ 681 ] ]
endobj
102 0 obj
<< /Subtype /CIDFontType0C /Length 743 >>
[BINARY STREAM]
endobj
101 0 obj
<< /Type /FontDescriptor /FontName /DPSGTM+LatinModernMath-Regular /Flags 4 /FontBBox [ -1042 -3060 4082 3560 ] /Ascent 806 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 153 /XHeight 431 /FontFile3 102 0 R >>
endobj
103 0 obj
<< /Length 722 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-DPSGTM-LatinModernMath-Regular-0)
%%Title: (TeX-DPSGTM-LatinModernMath-Regular-0 TeX DPSGTM-LatinModernMath-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (DPSGTM-LatinModernMath-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-DPSGTM-LatinModernMath-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
1 beginbfchar
<0258> <0033>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
81 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /DPSGTM+LatinModernMath-Regular /DescendantFonts [ 104 0 R ] /ToUnicode 103 0 R >>
endobj
104 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /DPSGTM+LatinModernMath-Regular /FontDescriptor 101 0 R /W 100 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
105 0 obj
[ 12 [ 778 ] 19 [ 500 ] 30 [ 778 ] 1319 [ 572 490 ] 3077 [ 833 ] 3081 [ 1000 1000 ] ]
endobj
107 0 obj
<< /Subtype /CIDFontType0C /Length 1511 >>
[BINARY STREAM]
endobj
106 0 obj
<< /Type /FontDescriptor /FontName /NDJELI+LatinModernMath-Regular /Flags 4 /FontBBox [ -1042 -3060 4082 3560 ] /Ascent 806 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 93 /XHeight 431 /FontFile3 107 0 R >>
endobj
108 0 obj
<< /Length 828 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-NDJELI-LatinModernMath-Regular-0)
%%Title: (TeX-NDJELI-LatinModernMath-Regular-0 TeX NDJELI-LatinModernMath-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (NDJELI-LatinModernMath-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-NDJELI-LatinModernMath-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
8 beginbfchar
<000C> <002B>
<0013> <0032>
<001E> <003D>
<0527> <D835DC65>
<0528> <D835DC66>
<0C05> <221A>
<0C09> <221A>
<0C0A> <221A>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
80 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /NDJELI+LatinModernMath-Regular /DescendantFonts [ 109 0 R ] /ToUnicode 108 0 R >>
endobj
109 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /NDJELI+LatinModernMath-Regular /FontDescriptor 106 0 R /W 105 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
84 0 obj
<< /Type /Pages /Count 1 /Kids [ 78 0 R ] >>
endobj
110 0 obj
<< /EmbeddedFiles 86 0 R >>
endobj
111 0 obj
<< /Type /Catalog /Pages 84 0 R /Names 110 0 R /MarkInfo 85 0 R/Lang (en)/Metadata 76 0 R/StructTreeRoot 5 0 R >>
endobj
112 0 obj
<< /Producer (LuaTeX)/Creator (TeX)/CreationDate (D:20160520090000Z)/ModDate (D:20160520090000Z) /Trapped /False >>
endobj
xref
0 113
0000000002 65535 f
0000017659 00000 n
0000000003 00000 f
0000000004 00000 f
0000000010 00000 f
0000025382 00000 n
0000017844 00000 n
0000018694 00000 n
0000020839 00000 n
0000019474 00000 n
0000000012 00000 f
0000019542 00000 n
0000000014 00000 f
0000019612 00000 n
0000000020 00000 f
0000020375 00000 n
0000019693 00000 n
0000020648 00000 n
0000020477 00000 n
0000020750 00000 n
0000000000 00000 f
0000020900 00000 n
0000000020 00000 n
0000000257 00000 n
0000000444 00000 n
0000000754 00000 n
0000000941 00000 n
0000001291 00000 n
0000001478 00000 n
0000001726 00000 n
0000021021 00000 n
0000021109 00000 n
0000021197 00000 n
0000021297 00000 n
0000021408 00000 n
0000001913 00000 n
0000002067 00000 n
0000021600 00000 n
0000021695 00000 n
0000021791 00000 n
0000021912 00000 n
0000022012 00000 n
0000022123 00000 n
0000002267 00000 n
0000002433 00000 n
0000022315 00000 n
0000022426 00000 n
0000022522 00000 n
0000022618 00000 n
0000022739 00000 n
0000002633 00000 n
0000022871 00000 n
0000022992 00000 n
0000023092 00000 n
0000023203 00000 n
0000002704 00000 n
0000002875 00000 n
0000023464 00000 n
0000023575 00000 n
0000023696 00000 n
0000003075 00000 n
0000023828 00000 n
0000023924 00000 n
0000024029 00000 n
0000024133 00000 n
0000024255 00000 n
0000024377 00000 n
0000024499 00000 n
0000024599 00000 n
0000024710 00000 n
0000003146 00000 n
0000003303 00000 n
0000024938 00000 n
0000025033 00000 n
0000025138 00000 n
0000025260 00000 n
0000003503 00000 n
0000017560 00000 n
0000017425 00000 n
0000015284 00000 n
0000034795 00000 n
0000031606 00000 n
0000029365 00000 n
0000027181 00000 n
0000035166 00000 n
0000017706 00000 n
0000017742 00000 n
0000018006 00000 n
0000018657 00000 n
0000019273 00000 n
0000025519 00000 n
0000026208 00000 n
0000025550 00000 n
0000026429 00000 n
0000027335 00000 n
0000027535 00000 n
0000028354 00000 n
0000027568 00000 n
0000028583 00000 n
0000029525 00000 n
0000029731 00000 n
0000030592 00000 n
0000029764 00000 n
0000030823 00000 n
0000031768 00000 n
0000031977 00000 n
0000033676 00000 n
0000032080 00000 n
0000033906 00000 n
0000034957 00000 n
0000035228 00000 n
0000035273 00000 n
0000035404 00000 n
trailer
<< /Size 113 /Root 111 0 R /Info 112 0 R /ID [ <2350CAD05F8A7AF0AA4058486855344F> <2350CAD05F8A7AF0AA4058486855344F> ] >>
startxref
35537
%%EOF

View File

@ -1,47 +0,0 @@
\ExplSyntaxOn
\sys_gset_rand_seed:n{42}
\ExplSyntaxOff
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
testphase = {phase-III,math,table},
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
\tagpdfsetup{math/mathml/structelem,attach-css=false}
\begin{document}
hello
\[
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
=
\begin{cases}
1 & \text{if $a=b$} \\
2 & \text{else}
\end{cases}
\]
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
\]
\[
\sum_a\underline c\dot bc'
\]
\begin{align}
abc&=def & e^{\mathrm{i}\pi}&=-1\\
\Big(1+2&=3\Big)\\
5
\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0$.
\end{document}

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
\ExplSyntaxOn
\sys_gset_rand_seed:n{42}
\ExplSyntaxOff
\DocumentMetadata{
lang=en,
testphase={phase-III,math},
pdfversion=2.0,
pdfstandard=ua-2,
pdfstandard=a-4f,
uncompress
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
% suppress writing of luamml-mathml
\tagpdfsetup{math/mathml/luamml/write=false} %
% suppress mathml-AF reading
\tagpdfsetup{math/mathml/sources=} %
\tagpdfsetup{math/mathml/AF=false,attach-css=false}
\begin{document}
\ExplSyntaxOn
\luamml_structelem:
$a = b \quad
\tagstructbegin{tag=mtext,stash}\tagmcbegin{}
\luamml_annotate:en{nucleus=true,structnum=\tag_get:n{struct_num}}
{\mbox{some~text~with~\emph{structure}}}
\tagmcend\tagstructend
$
\ExplSyntaxOff
\end{document}

View File

@ -1,783 +0,0 @@
%PDF-2.0
%ÌÕÁÔÅØÐÄÆ
22 0 obj
<< /N 3 /Length 3268 >>
[BINARY STREAM]
endobj
23 0 obj
<< /Type /OutputIntent /S /GTS_PDFA1 /DestOutputProfile 22 0 R /OutputConditionIdentifier (IEC\040sRGB) /Info (IEC\04061966-2.1\040Default\040RGB\040colour\040space\040-\040sRGB) /RegistryName (http://www.iec.ch) >>
endobj
29 0 obj
<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 192 >>
stream
$a=b\quad \tagstructbegin {tag=mtext,stash}\tagmcbegin {}\luamml_annotate:en {nucleus=true,structnum=\tag_get:n {struct_num}}{\mbox {some text with \emph {structure}}}\tagmcend \tagstructend $
endstream
endobj
30 0 obj
<< /Type /Filespec /AFRelationship /Source /Desc (TeX source) /F (tag-AFfile1.tex) /UF <FEFF007400610067002D0041004600660069006C00650031002E007400650078> /EF<</F 29 0 R/UF 29 0 R>> >>
endobj
36 0 obj
<< /O/NSO/NS 13 0 R/lspace(0.278em)/rspace(0.278em) >>
endobj
39 0 obj
<< /O/NSO/NS 13 0 R/width(9.963pt) >>
endobj
40 0 obj
<< /Type /Metadata /Subtype /XML /Length 16669 >>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"
xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"
xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"
xmlns:pdfxid="http://www.npes.org/pdfx/ns/id/"
xmlns:prism="http://prismstandard.org/namespaces/basic/3.0/"
xmlns:stFnt="http://ns.adobe.com/xap/1.0/sType/Font#"
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#"
xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type#"
xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field#"
xmlns:pdfd="http://pdfa.org/declarations/">
<pdfaExtension:schemas>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>
<pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>OriginalDocumentID</pdfaProperty:name>
<pdfaProperty:valueType>URI</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>The common identifier for all versions and renditions of a document.</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/A Identification Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>year</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Year of standard</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>rev</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Revision year of standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/UA Universal Accessibility Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfuaid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.aiim.org/pdfua/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>part</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Part of ISO 14289 standard</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>rev</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Revision of ISO 14289 standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF/X ID Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfxid</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://www.npes.org/pdfx/ns/id/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>GTS_PDFXVersion</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>ID of PDF/X standard</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PRISM Basic Metadata</pdfaSchema:schema>
<pdfaSchema:prefix>prism</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://prismstandard.org/namespaces/basic/3.0/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>complianceProfile</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>PRISM specification compliance profile to which this document adheres</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>publicationName</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication name</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>aggregationType</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication type</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>bookEdition</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Edition of the book in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>volume</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication volume number</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>number</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Publication issue number within a volume</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>pageRange</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Page range for the document within the print version of its publication</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>issn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISSN for the printed publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>eIssn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISSN for the electronic publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>isbn</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ISBN for the publication in which the document was published</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>doi</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Digital Object Identifier for the document</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>url</pdfaProperty:name>
<pdfaProperty:valueType>URL</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>URL at which the document can be found</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>byteCount</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Approximate file size in octets</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>pageCount</pdfaProperty:name>
<pdfaProperty:valueType>Integer</pdfaProperty:valueType>
<pdfaProperty:category>internal</pdfaProperty:category>
<pdfaProperty:description>Number of pages in the print version of the document</pdfaProperty:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>subtitle</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>Document's subtitle</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaSchema:schema>PDF Declarations Schema</pdfaSchema:schema>
<pdfaSchema:prefix>pdfd</pdfaSchema:prefix>
<pdfaSchema:namespaceURI>http://pdfa.org/declarations/</pdfaSchema:namespaceURI>
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:name>declarations</pdfaProperty:name>
<pdfaProperty:valueType>Bag declaration</pdfaProperty:valueType>
<pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>An unordered array of PDF Declaration entries, where each PDF Declaration representing a statement of conformance with an identified external standard or profile, along with optional information identifying the nature of the claim.</pdfaProperty:description>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
<pdfaSchema:valueType>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaType:type>claim</pdfaType:type>
<pdfaType:namespaceURI>http://pdfa.org/declarations/</pdfaType:namespaceURI>
<pdfaType:prefix>pdfd</pdfaType:prefix>
<pdfaType:description>A structure describing properties of an individualclaim.</pdfaType:description>
<pdfaType:field>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>claimReport</pdfaField:name>
<pdfaField:valueType>Text</pdfaField:valueType>
<pdfaField:description>A URL to a report containing details of the specific conformance claim.</pdfaField:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>claimCredentials</pdfaField:name>
<pdfaField:valueType>Text</pdfaField:valueType>
<pdfaField:description>The claimant's credentials.</pdfaField:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>claimDate</pdfaField:name>
<pdfaField:valueType>Text</pdfaField:valueType>
<pdfaField:description>A date identifying when the claim was made.</pdfaField:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>claimBy</pdfaField:name>
<pdfaField:valueType>Text</pdfaField:valueType>
<pdfaField:description>The name of the organization and/or individual and/or software making the claim.</pdfaField:description>
</rdf:li>
</rdf:Seq>
</pdfaType:field>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaType:type>declaration</pdfaType:type>
<pdfaType:namespaceURI>http://pdfa.org/declarations/</pdfaType:namespaceURI>
<pdfaType:prefix>pdfd</pdfaType:prefix>
<pdfaType:description>A structure describing a single PDF Declaration asserting conformance with an externally-identified standard or profile.</pdfaType:description>
<pdfaType:field>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>conformsTo</pdfaField:name>
<pdfaField:valueType>Text</pdfaField:valueType>
<pdfaField:description>A property containing a URI specifying the standard or profile by the PDF Declaration. This property is intended to mirror the Dublin Core property dc:conformsTo.</pdfaField:description>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaField:name>claimData</pdfaField:name>
<pdfaField:valueType>Bag claim</pdfaField:valueType>
<pdfaField:description>An unordered array of claim data, where each claim identifies the nature of the claim.</pdfaField:description>
</rdf:li>
</rdf:Seq>
</pdfaType:field>
</rdf:li>
</rdf:Seq>
</pdfaSchema:valueType>
</rdf:li>
</rdf:Bag>
</pdfaExtension:schemas>
<pdf:Producer>luahbtex-NN.NN.NN</pdf:Producer>
<pdf:PDFVersion>2.0</pdf:PDFVersion>
<pdfaid:part>4</pdfaid:part>
<pdfaid:conformance>F</pdfaid:conformance>
<pdfaid:rev>2020</pdfaid:rev>
<pdfuaid:part>2</pdfuaid:part>
<pdfuaid:rev>2024</pdfuaid:rev>
<pdfd:declarations>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfd:conformsTo>http://pdfa.org/declarations/wtpdf#accessibility1.0</pdfd:conformsTo>
<pdfd:claimData>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfd:claimBy>LaTeX Project</pdfd:claimBy>
<pdfd:claimDate>2016-05-20</pdfd:claimDate>
</rdf:li>
</rdf:Bag>
</pdfd:claimData>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfd:conformsTo>http://pdfa.org/declarations/wtpdf#reuse1.0</pdfd:conformsTo>
<pdfd:claimData>
<rdf:Bag>
<rdf:li rdf:parseType="Resource">
<pdfd:claimBy>LaTeX Project</pdfd:claimBy>
<pdfd:claimDate>2016-05-20</pdfd:claimDate>
</rdf:li>
</rdf:Bag>
</pdfd:claimData>
</rdf:li>
</rdf:Bag>
</pdfd:declarations>
<dc:type>
<rdf:Bag>
<rdf:li>Text</rdf:li>
</rdf:Bag>
</dc:type>
<dc:language>
<rdf:Bag>
<rdf:li>en</rdf:li>
</rdf:Bag>
</dc:language>
<dc:date>
<rdf:Seq>
<rdf:li>2016-05-20T09:00:00Z</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>test_structnum.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
<xmp:CreateDate>2016-05-20T09:00:00Z</xmp:CreateDate>
<xmp:ModifyDate>2016-05-20T09:00:00Z</xmp:ModifyDate>
<xmp:MetadataDate>2016-05-20T09:00:00Z</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:2b6fecb9-b74a-4265-883d-138c87e7152f</xmpMM:DocumentID>
<xmpMM:InstanceID>uuid:0a57c455-157a-4141-8c19-6237d832fc80</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
endstream
endobj
43 0 obj
<< /Length 653 >>
stream
/opacity1 gs
/Artifact BMC
EMC
/mi<</MCID 0>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 148.712 657.235 Tm [<0510>]TJ
ET
EMC
/mo<</MCID 1>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 156.75 657.235 Tm [<001E>]TJ
ET
EMC
/mi<</MCID 2>> BDC
BT
/F20 9.96264 Tf
1 0 0 1 167.268 657.235 Tm [<0511>]TJ
ET
EMC
/mtext<</MCID 3>> BDC
BT
/F15 9.96264 Tf
1 0 0 1 181.505 657.235 Tm [<00620051004B0032006700690032007400690067007200420069003F0067>]TJ
ET
EMC
/Em<</MCID 4>> BDC
BT
/F32 9.96264 Tf
1 0 0 1 249.898 657.235 Tm [<006200690060006D002B0069006D0060>51<0032>]TJ
ET
EMC
/Artifact BMC
EMC
/Artifact BMC
BT
/F15 9.96264 Tf
1 0 0 1 303.133 89.365 Tm [<0052>]TJ
ET
EMC
/Artifact BMC
EMC
endstream
endobj
42 0 obj
<< /Type /Page /Contents 43 0 R /Resources 41 0 R /MediaBox [ 0 0 612 792 ] /StructParents 0/Tabs /S /Parent 47 0 R >>
endobj
41 0 obj
<< /ExtGState 1 0 R /Font << /F20 44 0 R /F15 45 0 R /F32 46 0 R >> >>
endobj
1 0 obj
<< /opacity1 <</ca 1/CA 1>> >>
endobj
48 0 obj
<< /Marked true >>
endobj
49 0 obj
[ 23 0 R ]
endobj
50 0 obj
<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20160520) >> /Length 115 >>
stream
The document was declared to be of type PDF/A-4f but hasn't any attachments. LaTeX therefore added this dummy file.
endstream
endobj
51 0 obj
<< /Type /Filespec /AFRelationship /Unspecified /Desc (note about PDF/A-4F) /F (pdf-A4f.txt) /UF <FEFF007000640066002D004100340066002E007400780074> /EF<</F 50 0 R/UF 50 0 R>> >>
endobj
52 0 obj
<< /Names[(pdf-A4f) 51 0 R] >>
endobj
6 0 obj
<< /Nums [0 [ 34 0 R 35 0 R 37 0 R 31 0 R 32 0 R]
] >>
endobj
53 0 obj
<< /Limits [(ID.002) (ID.014)]/Names [(ID.002) 21 0 R (ID.003) 24 0 R (ID.004) 25 0 R (ID.005) 26 0 R (ID.006) 27 0 R (ID.007) 28 0 R (ID.008) 31 0 R (ID.009) 32 0 R (ID.010) 33 0 R (ID.011) 34 0 R (ID.012) 35 0 R (ID.013) 37 0 R (ID.014) 38 0 R ] >>
endobj
54 0 obj
<< /Kids [53 0 R] >>
endobj
7 0 obj
<< /Artifact /NonStruct /DocumentFragment /Art /Aside /Note /H7 /H6 /H8 /H6 /H9 /H6 /H10 /H6 /Title /P /FENote /Note /Sub /Span /Em /Span /Strong /Span /title /P /part /P /section /H1 /subsection /H2 /subsubsection /H3 /paragraph /H4 /subparagraph /H5 /list /L /itemize /L /enumerate /L /description /L /quote /BlockQuote /quotation /BlockQuote /verbatim /P /item /LI /itemlabel /Lbl /itembody /LBody /footnote /Note /footnotemark /Lbl /footnotelabel /Lbl /text-unit /Part /text /P /theorem-like /Sect /codeline /Span /float /Note /figures /Sect /tables /Sect >>
endobj
55 0 obj
<< /justify <</O/Layout/TextAlign/Justify>>
/inline <</O/Layout/Placement/Inline>>
>>
endobj
9 0 obj
<< /Type /Namespace /NS (http://iso.org/pdf/ssn) >>
endobj
11 0 obj
<< /Type /Namespace /NS (http://iso.org/pdf2/ssn) >>
endobj
13 0 obj
<< /Type /Namespace /NS (http://www.w3.org/1998/Math/MathML) >>
endobj
16 0 obj
<< /title [/Title 11 0 R] /part [/Title 11 0 R] /section [/H1 11 0 R] /subsection [/H2 11 0 R] /subsubsection [/H3 11 0 R] /paragraph [/H4 11 0 R] /subparagraph [/H5 11 0 R] /list [/L 11 0 R] /itemize [/L 11 0 R] /enumerate [/L 11 0 R] /description [/L 11 0 R] /quote [/BlockQuote 9 0 R] /quotation [/BlockQuote 9 0 R] /verbatim [/P 11 0 R] /item [/LI 11 0 R] /itemlabel [/Lbl 11 0 R] /itembody [/LBody 11 0 R] /footnote [/FENote 11 0 R] /footnotemark [/Lbl 11 0 R] /footnotelabel [/Lbl 11 0 R] /text-unit [/Part 11 0 R] /text [/P 11 0 R] /theorem-like [/Sect 11 0 R] /codeline [/Sub 11 0 R] /float [/Aside 11 0 R] /figures [/Sect 11 0 R] /tables [/Sect 11 0 R] >>
endobj
15 0 obj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/dflt) /RoleMapNS 16 0 R >>
endobj
18 0 obj
<< /chapter [/H1 11 0 R] /section [/H2 11 0 R] /subsection [/H3 11 0 R] /subsubsection [/H4 11 0 R] /paragraph [/H5 11 0 R] /subparagraph [/H6 11 0 R] >>
endobj
17 0 obj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/book) /RoleMapNS 18 0 R >>
endobj
19 0 obj
<< /Type /Namespace /NS (data:,C9B55C18-275C-494E-C10F-E4B83CD03F23) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R ]
endobj
21 0 obj
<< /Type /StructElem /S /Document /NS 11 0 R /P 5 0 R /K 26 0 R /ID (ID.002) >>
endobj
24 0 obj
<< /Type /StructElem /S /Artifact /NS 15 0 R /P 5 0 R /ID (ID.003) >>
endobj
25 0 obj
<< /Type /StructElem /S /Artifact /NS 15 0 R /P 5 0 R /ID (ID.004) >>
endobj
26 0 obj
<< /Type /StructElem /S /text-unit /NS 15 0 R /P 21 0 R /K 27 0 R /ID (ID.005) >>
endobj
27 0 obj
<< /Type /StructElem /C /justify /S /text /NS 15 0 R /P 26 0 R /K [ 28 0 R ] /ID (ID.006) >>
endobj
28 0 obj
<< /Type /StructElem /C /inline /AF [30 0 R] /T <FEFF006D006100740068> /S /Formula /NS 11 0 R /P 27 0 R /K [ 33 0 R] /ID (ID.007) >>
endobj
31 0 obj
<< /Type /StructElem /S /mtext /NS 13 0 R /P 33 0 R /K [<</Type /MCR /Pg 42 0 R /MCID 3>> 32 0 R ] /ID (ID.008) >>
endobj
32 0 obj
<< /Type /StructElem /S /Em /NS 11 0 R /P 31 0 R /K <</Type /MCR /Pg 42 0 R /MCID 4>> /ID (ID.009) >>
endobj
33 0 obj
<< /Type /StructElem /S /math /NS 13 0 R /P 28 0 R /K [34 0 R 35 0 R 37 0 R 38 0 R 31 0 R] /ID (ID.010) >>
endobj
34 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 33 0 R /K <</Type /MCR /Pg 42 0 R /MCID 0>> /ID (ID.011) >>
endobj
35 0 obj
<< /Type /StructElem /A 36 0 R /S /mo /NS 13 0 R /P 33 0 R /K <</Type /MCR /Pg 42 0 R /MCID 1>> /ID (ID.012) >>
endobj
37 0 obj
<< /Type /StructElem /S /mi /NS 13 0 R /P 33 0 R /K <</Type /MCR /Pg 42 0 R /MCID 2>> /ID (ID.013) >>
endobj
38 0 obj
<< /Type /StructElem /A 39 0 R /S /mspace /NS 13 0 R /P 33 0 R /ID (ID.014) >>
endobj
5 0 obj
<< /Type /StructTreeRoot /Namespaces 8 0 R /IDTree 54 0 R /ClassMap 55 0 R /ParentTree 6 0 R /RoleMap 7 0 R /K 21 0 R >>
endobj
56 0 obj
[ 43 [ 460 ] 50 [ 460 ] 96 [ 422 ] 98 [ 409 ] 105 [ 332 ] 109 [ 537 ] ]
endobj
58 0 obj
<< /Subtype /CIDFontType0C /Length 1274 >>
[BINARY STREAM]
endobj
57 0 obj
<< /Type /FontDescriptor /FontName /ADNFRA+LMRoman10-Italic /Flags 4 /FontBBox [ -458 -290 1386 1125 ] /Ascent 1125 /CapHeight 683 /Descent -290 /ItalicAngle -15 /StemV 102 /XHeight 431 /FontFile3 58 0 R >>
endobj
59 0 obj
<< /Length 757 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-ADNFRA-LMRoman10-Italic-0)
%%Title: (TeX-ADNFRA-LMRoman10-Italic-0 TeX ADNFRA-LMRoman10-Italic 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (ADNFRA-LMRoman10-Italic)
/Supplement 0
>> def
/CMapName /TeX-Identity-ADNFRA-LMRoman10-Italic def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
6 beginbfchar
<002B> <0063>
<0032> <0065>
<0060> <0072>
<0062> <0073>
<0069> <0074>
<006D> <0075>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
46 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /ADNFRA+LMRoman10-Italic /DescendantFonts [ 60 0 R ] /ToUnicode 59 0 R >>
endobj
60 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /ADNFRA+LMRoman10-Italic /FontDescriptor 57 0 R /W 56 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
61 0 obj
[ 50 [ 444 ] 63 [ 556 ] 66 [ 278 ] 75 [ 833 ] 81 [ 500 500 ] 98 [ 394 ] 103 [ 333 ] 105 [ 389 ] 114 [ 722 ] 116 [ 528 ] ]
endobj
63 0 obj
<< /Subtype /CIDFontType0C /Length 1812 >>
[BINARY STREAM]
endobj
62 0 obj
<< /Type /FontDescriptor /FontName /GZYIXU+LMRoman10-Regular /Flags 4 /FontBBox [ -430 -290 1417 1127 ] /Ascent 1127 /CapHeight 683 /Descent -290 /ItalicAngle 0 /StemV 93 /XHeight 431 /FontFile3 63 0 R >>
endobj
64 0 obj
<< /Length 833 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-GZYIXU-LMRoman10-Regular-0)
%%Title: (TeX-GZYIXU-LMRoman10-Regular-0 TeX GZYIXU-LMRoman10-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (GZYIXU-LMRoman10-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-GZYIXU-LMRoman10-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
11 beginbfchar
<0032> <0065>
<003F> <0068>
<0042> <0069>
<004B> <006D>
<0051> <006F>
<0052> <0031>
<0062> <0073>
<0067> <0020>
<0069> <0074>
<0072> <0077>
<0074> <0078>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
45 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /GZYIXU+LMRoman10-Regular /DescendantFonts [ 65 0 R ] /ToUnicode 64 0 R >>
endobj
65 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /GZYIXU+LMRoman10-Regular /FontDescriptor 62 0 R /W 61 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
66 0 obj
[ 30 [ 778 ] 1296 [ 529 429 ] ]
endobj
68 0 obj
<< /Subtype /CIDFontType0C /Length 984 >>
[BINARY STREAM]
endobj
67 0 obj
<< /Type /FontDescriptor /FontName /NFEDYW+LatinModernMath-Regular /Flags 4 /FontBBox [ -1042 -3060 4082 3560 ] /Ascent 806 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 93 /XHeight 431 /FontFile3 68 0 R >>
endobj
69 0 obj
<< /Length 758 >>
stream
%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-NFEDYW-LatinModernMath-Regular-0)
%%Title: (TeX-NFEDYW-LatinModernMath-Regular-0 TeX NFEDYW-LatinModernMath-Regular 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (NFEDYW-LatinModernMath-Regular)
/Supplement 0
>> def
/CMapName /TeX-Identity-NFEDYW-LatinModernMath-Regular def
/CMapType 2 def
1 begincodespacerange
<0000> <FFFF>
endcodespacerange
0 beginbfrange
endbfrange
3 beginbfchar
<001E> <003D>
<0510> <D835DC4E>
<0511> <D835DC4F>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
endstream
endobj
44 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /NFEDYW+LatinModernMath-Regular /DescendantFonts [ 70 0 R ] /ToUnicode 69 0 R >>
endobj
70 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /NFEDYW+LatinModernMath-Regular /FontDescriptor 67 0 R /W 66 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
47 0 obj
<< /Type /Pages /Count 1 /Kids [ 42 0 R ] >>
endobj
71 0 obj
<< /EmbeddedFiles 52 0 R >>
endobj
72 0 obj
<< /Type /Catalog /Pages 47 0 R /Names 71 0 R /MarkInfo 48 0 R/OutputIntents 49 0 R/Lang (en)/Metadata 40 0 R/StructTreeRoot 5 0 R >>
endobj
xref
0 73
0000000002 65535 f
0000021940 00000 n
0000000003 00000 f
0000000004 00000 f
0000000010 00000 f
0000026513 00000 n
0000022542 00000 n
0000022917 00000 n
0000024964 00000 n
0000023599 00000 n
0000000012 00000 f
0000023667 00000 n
0000000014 00000 f
0000023737 00000 n
0000000020 00000 f
0000024500 00000 n
0000023818 00000 n
0000024773 00000 n
0000024602 00000 n
0000024875 00000 n
0000000000 00000 f
0000025025 00000 n
0000000020 00000 n
0000003353 00000 n
0000025123 00000 n
0000025211 00000 n
0000025299 00000 n
0000025399 00000 n
0000025510 00000 n
0000003586 00000 n
0000003921 00000 n
0000025661 00000 n
0000025795 00000 n
0000025916 00000 n
0000026041 00000 n
0000026162 00000 n
0000004121 00000 n
0000026294 00000 n
0000026415 00000 n
0000004192 00000 n
0000004246 00000 n
0000021853 00000 n
0000021718 00000 n
0000021005 00000 n
0000035152 00000 n
0000032636 00000 n
0000029136 00000 n
0000035518 00000 n
0000021987 00000 n
0000022023 00000 n
0000022050 00000 n
0000022301 00000 n
0000022495 00000 n
0000022613 00000 n
0000022880 00000 n
0000023496 00000 n
0000026650 00000 n
0000028096 00000 n
0000026738 00000 n
0000028319 00000 n
0000029289 00000 n
0000029488 00000 n
0000031522 00000 n
0000029626 00000 n
0000031743 00000 n
0000032790 00000 n
0000032990 00000 n
0000034106 00000 n
0000033038 00000 n
0000034334 00000 n
0000035312 00000 n
0000035580 00000 n
0000035624 00000 n
trailer
<< /Size 73 /Root 72 0 R /ID [ <2350CAD05F8A7AF0AA4058486855344F> <2350CAD05F8A7AF0AA4058486855344F> ] >>
startxref
35774
%%EOF

View File

@ -1,196 +0,0 @@
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑎</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mi>𝑏</mi>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mo fence="true" lspace="0" rspace="0" symmetric="true">(</mo>
<mspace width="-4.981pt" />
<mpadded lspace="+4.981pt" width="+9.963pt">
<mtable>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtable>
</mpadded>
<mspace width="-4.981pt" />
<mo fence="true" lspace="0" rspace="0" symmetric="true">)</mo>
</mrow>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mrow>
<mo fence="true" lspace="0" rspace="0" symmetric="true">{</mo>
<mpadded lspace="+4.981pt" width="+9.963pt">
<mtable>
<mtr>
<mtd columnalign="left">
<mn>1</mn>
</mtd>
<mtd columnalign="left">
<mtext>if&#160;
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑎</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mi>𝑏</mi>
</math></mtext>
</mtd>
</mtr>
<mtr>
<mtd columnalign="left">
<mn>2</mn>
</mtd>
<mtd columnalign="left">
<mtext>else</mtext>
</mtd>
</mtr>
</mtable>
</mpadded>
<mspace width="1.196pt" />
</mrow>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mi>𝑥</mi>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mfrac>
<mrow>
<mo lspace="0" rspace="0.222em"></mo>
<mi>𝑏</mi>
<mo lspace="0.222em" rspace="0.222em">±</mo>
<msqrt>
<mrow>
<msup>
<mi>𝑏</mi>
<mn>2</mn>
</msup>
<mo lspace="0.222em" rspace="0.222em"></mo>
<mn>4</mn>
<mi>𝑎</mi>
<mi>𝑐</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>𝑎</mi>
</mrow>
</mfrac>
<mo lspace="0" rspace="0">.</mo>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<munder>
<mo lspace="0" movablelimits="true" rspace="0.167em">∑</mo>
<mi>𝑎</mi>
</munder>
<munder>
<mi>𝑐</mi>
<mo>_</mo>
</munder>
<mover>
<mi>𝑏</mi>
<mo stretchy="true">.</mo>
</mover>
<msup>
<mi>𝑐</mi>
<mi mathvariant="normal"></mi>
</msup>
</math>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mtable class="align" columnalign="left right left right left" columnspacing="0 0 .8em 0" displaystyle="true" intent=":system-of-equations">
<mtr>
<mtd>
<mi>𝑎</mi>
<mi>𝑏</mi>
<mi>𝑐</mi>
</mtd>
<mtd intent=":pause-medium">
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mi>𝑑</mi>
<mi>𝑒</mi>
<mi>𝑓</mi>
</mtd>
<mtd>
<msup>
<mi>𝑒</mi>
<mrow>
<mi mathvariant="normal">i</mi>
<mi>𝜋</mi>
</mrow>
</msup>
</mtd>
<mtd intent=":pause-medium">
<mo lspace="0.278em" rspace="0">=</mo>
<mo lspace="0.278em" rspace="0"></mo>
<mn>1</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mo fence="true" lspace="0" maxsize="17.861pt" minsize="17.861pt" rspace="0" symmetric="true">(</mo>
<mn>1</mn>
<mo lspace="0.222em" rspace="0.222em">+</mo>
<mn>2</mn>
</mtd>
<mtd intent=":pause-medium">
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mn>3</mn>
<mo fence="true" lspace="0" maxsize="17.861pt" minsize="17.861pt" rspace="0" symmetric="true">)</mo>
</mtd>
<mtd></mtd>
<mtd intent=":pause-medium"></mtd>
</mtr>
<mtr>
<mtd>
<mn>5</mn>
</mtd>
<mtd intent=":pause-medium"></mtd>
<mtd></mtd>
<mtd intent=":pause-medium"></mtd>
</mtr>
</mtable>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi mathvariant="normal">sin</mi>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.222em" rspace="0.222em"></mo>
<mi mathvariant="normal">sin</mi>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0.222em" rspace="0.222em">+</mo>
<mn>2</mn>
<mi>𝜋</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mn>0</mn>
</math>

View File

@ -1,48 +0,0 @@
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
testphase = {phase-III,table,math},
}
\input{regression-test}
\documentclass{article}
\usepackage{unicode-math}
\begin{document}
\ExplSyntaxOn
\luamml_set_filename:n {
\jobname .mml
}
\luamml_process:
\luamml_begin_single_file:
\ExplSyntaxOff
\[
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}
=
\begin{cases}
1 & \text{if $a=b$}\\
2 & \text{else}
\end{cases}
\]
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
\]
\[
\sum_a\underline c\dot bc'
\]
\begin{align}
abc&=def & e^{\mathrm{i}\pi}&=-1\\
\Big(1+2&=3\Big)\\
5
\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0$.
\end{document}

View File

@ -1,51 +0,0 @@
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mi mathvariant="normal">∅</mi>
<mo lspace="0.278em" rspace="0">⊧</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">(</mo>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑝</mi>
<mo lspace="0.278em" rspace="0.278em" stretchy="false">⇒</mo>
<mi>𝑞</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">⇒</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">(</mo>
<mi>𝑞</mi>
<mo lspace="0.278em" rspace="0.278em" stretchy="false">⇒</mo>
<mi>𝑟</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">⇒</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">(</mo>
<mi>𝑝</mi>
<mo lspace="0.278em" rspace="0" stretchy="false">⇒</mo>
<mo lspace="0.278em" rspace="0" stretchy="false">(</mo>
<mi>𝑞</mi>
<mo lspace="0.278em" rspace="0.278em" stretchy="false">⇒</mo>
<mi>𝑟</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
</math>
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mi mathvariant="normal">s</mi>
<mi mathvariant="normal">i</mi>
<mi mathvariant="normal">n</mi>
</mrow>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.222em" rspace="0.222em"></mo>
<mrow>
<mi mathvariant="normal">s</mi>
<mi mathvariant="normal">i</mi>
<mi mathvariant="normal">n</mi>
</mrow>
<mo lspace="0" rspace="0" stretchy="false">(</mo>
<mi>𝑥</mi>
<mo lspace="0.222em" rspace="0.222em">+</mo>
<mn>2</mn>
<mi>𝜋</mi>
<mo lspace="0" rspace="0" stretchy="false">)</mo>
<mo lspace="0.278em" rspace="0.278em">=</mo>
<mn>0</mn>
</math>

View File

@ -1,20 +0,0 @@
\documentclass{article}
\usepackage{amsmath}
\usepackage{luamml-demo}
\begin{document}
\[
\emptyset\models((p\Rightarrow q)\Rightarrow(q\Rightarrow r))\Rightarrow (p\Rightarrow (q\Rightarrow r))
\WriteoutFormula
\]
%\begin{align}
% abc&=def & e^{\mathrm{i}\pi}&=-1\\
% \Big(1+2&=3\Big)\\
% &4\\
% 5
%\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0\WriteoutFormula$.
\end{document}

View File

@ -1,218 +0,0 @@
LUAMML_INSTRUCTION:REGISTER_MAPPING:2:oms
LUAMML_INSTRUCTION:REGISTER_MAPPING:1:oml
LUAMML_INSTRUCTION:REGISTER_MAPPING:3:omx
LUAMML_MARK:1:count=3,nucleus=true,core={[0]='mi','\u{22a7}'},
LUAMML_MARK_END
LUAMML_FORMULA_BEGIN:1:3:mrow:
### display math mode entered at line 6
\mathord
.\fam2 ;
\write3{LUAMML_MARK_REF:1:}
\mathrel
.\fam2 j
\mathrel
.\mkern-3.0mu
\mathrel
.\fam0 =
\mathopen
.\fam0 (
\mathopen
.\fam0 (
\mathord
.\fam1 p
\mathrel
.\fam2 )
\mathord
.\fam1 q
\mathclose
.\fam0 )
\mathrel
.\fam2 )
\mathopen
.\fam0 (
\mathord
.\fam1 q
\mathrel
.\fam2 )
\mathord
.\fam1 r
\mathclose
.\fam0 )
\mathclose
.\fam0 )
\mathrel
.\fam2 )
\mathopen
.\fam0 (
\mathord
.\fam1 p
\mathrel
.\fam2 )
\mathopen
.\fam0 (
\mathord
.\fam1 q
\mathrel
.\fam2 )
\mathord
.\fam1 r
\mathclose
.\fam0 )
\mathclose
.\fam0 )
### vertical mode entered at line 0
### current page:
\write-{}
\glue(\topskip) 10.0
\hbox(0.0+0.0)x345.0, glue set 330.0fil
.\hbox(0.0+0.0)x15.0
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
total height 10.0
goal height 550.0
prevdepth 0.0, prevgraf 1 line
! OK
LUAMML_FORMULA_END
LUAMML_FORMULA_BEGIN:2:3:mrow:
### math mode entered at line 18
\mathop\nolimits
.\kern 0.0
.\mathord
..\fam0 s
.\mathord
..\fam0 i
.\mathord
..\fam0 n
\mathopen
.\fam0 (
\mathord
.\fam1 x
\mathclose
.\fam0 )
\mathbin
.\fam2 ^^@
\mathop\nolimits
.\kern 0.0
.\mathord
..\fam0 s
.\mathord
..\fam0 i
.\mathord
..\fam0 n
\mathopen
.\fam0 (
\mathord
.\fam1 x
\mathbin
.\fam0 +
\mathord
.\fam0 2
\mathord
.\fam1 ^^Y
\mathclose
.\fam0 )
\mathrel
.\fam0 =
\mathord
.\fam0 0
### horizontal mode entered at line 18
\hbox(0.0+0.0)x15.0
\OT1/cmr/m/n/10 E
\OT1/cmr/m/n/10 s
\glue 3.33333 plus 1.66666 minus 1.11111
\OT1/cmr/m/n/10 g
\OT1/cmr/m/n/10 i
\OT1/cmr/m/n/10 l
\OT1/cmr/m/n/10 t
\glue 3.33333 plus 1.66666 minus 1.11111
spacefactor 1000
### vertical mode entered at line 0
### current page:
\write-{}
\glue(\topskip) 10.0
\hbox(0.0+0.0)x345.0, glue set 330.0fil
.\hbox(0.0+0.0)x15.0
.\penalty 10000
.\glue(\parfillskip) 0.0 plus 1.0fil
.\glue(\rightskip) 0.0
\penalty 10000
\glue(\abovedisplayshortskip) 0.0 plus 3.0
\glue(\baselineskip) 4.5
\hbox(7.5+2.5)x185.77597, shifted 79.61201, display
.\OMS/cmsy/m/n/10 ;
.\write3{LUAMML_MARK_REF:1:}
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 j
.\hbox(0.0+0.0)x-1.66663
..\kern -1.66663
.\OT1/cmr/m/n/10 =
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OT1/cmr/m/n/10 (
.\OT1/cmr/m/n/10 (
.\OML/cmm/m/it/10 p
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OML/cmm/m/it/10 q
.\kern0.35878
.\OT1/cmr/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OT1/cmr/m/n/10 (
.\OML/cmm/m/it/10 q
.\kern0.35878
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OML/cmm/m/it/10 r
.\kern0.27779
.\OT1/cmr/m/n/10 )
.\OT1/cmr/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OT1/cmr/m/n/10 (
.\OML/cmm/m/it/10 p
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OT1/cmr/m/n/10 (
.\OML/cmm/m/it/10 q
.\kern0.35878
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OMS/cmsy/m/n/10 )
.\glue(\thickmuskip) 2.77771 plus 2.77771
.\OML/cmm/m/it/10 r
.\kern0.27779
.\OT1/cmr/m/n/10 )
.\OT1/cmr/m/n/10 )
\penalty 0
\glue(\belowdisplayshortskip) 6.0 plus 3.0 minus 3.0
\glue(\parskip) 0.0 plus 1.0
\glue(\parskip) 0.0
total height 30.5 plus 7.0 minus 3.0
goal height 550.0
prevdepth 2.5
! OK
LUAMML_FORMULA_END
LUAMML_MARK_REF:1:

View File

@ -1,20 +0,0 @@
\documentclass{article}
\usepackage{amsmath}
\usepackage{luamml-demo}
\begin{document}
\[
\emptyset\models((p\Rightarrow q)\Rightarrow(q\Rightarrow r))\Rightarrow (p\Rightarrow (q\Rightarrow r))
\WriteoutFormula
\]
%\begin{align}
% abc&=def & e^{\mathrm{i}\pi}&=-1\\
% \Big(1+2&=3\Big)\\
% &4\\
% 5
%\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0\WriteoutFormula$.
\end{document}