diff --git a/grammars/basicdoc.rnc b/grammars/basicdoc.rnc index 279e999..9d6a68c 100644 --- a/grammars/basicdoc.rnc +++ b/grammars/basicdoc.rnc @@ -1068,9 +1068,10 @@ latexmath = element latexmath { text } ## Encoding of AsciiMath asciimath = element asciimath { text } -## Encoding of MathML: the official W3C MathML 3.0 grammar (namespace +## Encoding of MathML: the official W3C MathML 4 grammar (namespace ## http://www.w3.org/1998/Math/MathML), via the metanorma wrapper in -## grammars/mathml/. See grammars/mathml/README.adoc and basicdoc-models#35. +## grammars/mathml/. See grammars/mathml/README.adoc, basicdoc-models#35, +## and the MathML 3 -> 4 migration: basicdoc-models#39 / metanorma#585. mathml = external "mathml/metanorma-mathml.rnc" StemAttributes = diff --git a/grammars/mathml/README.adoc b/grammars/mathml/README.adoc index 97641f5..4b07468 100644 --- a/grammars/mathml/README.adoc +++ b/grammars/mathml/README.adoc @@ -1,17 +1,48 @@ -= Vendored MathML 3.0 RelaxNG grammar += Vendored MathML 4 RelaxNG grammar -`mathml3*.rnc` are the **unmodified** W3C MathML 3.0 RelaxNG Compact schema -files, retrieved from https://www.w3.org/Math/RelaxNG/mathml3/ and used under the +`mathml4*.rnc` are the W3C MathML 4 RelaxNG Compact schema files, retrieved +from https://www.w3.org/Math/RelaxNG/mathml4/ on **2026-07-16** and used under +the https://www.w3.org/Consortium/Legal/2002/copyright-software-20021231[W3C Software -and Document License]. +and Document License]. They are generated by W3C from +https://github.com/w3c/mathml-schema. + +IMPORTANT: unlike the MathML 3 vendoring (which was unmodified), these files +carry **marked modifications**, each tagged in-place with a +`METANORMA MODIFICATION (basicdoc-models#39)` comment preserving the upstream +text. They fall into two classes: (a) the draft-generated grammar violates +RELAX NG's duplicate-attribute restriction throughout the full-profile +composition (jing rejects it outright: `data-other`, `dir`/`mathsize`/ +`mathvariant`, `id`, `alttext`, `maxsize`, `href`, `attributionsrc`, +`displaystyle`, `encoding`); (b) the `anyElement`/`annotation-xml` combine +re-opens and a nested-include override had to be adjusted so the metanorma +wrapper's foreign-markup bans remain expressible for both jing and libxml2. +Diff against the upstream snapshot to enumerate; re-audit all of them when +re-syncing at CR/REC (upstream may have fixed the duplicates by then). + +Include graph: `mathml4.rnc` includes `mathml4-presentation.rnc` (which +includes `mathml4-core.rnc`) and `mathml4-content.rnc` (which includes +`mathml4-strict-content.rnc`). + +IMPORTANT: MathML 4 is, as of the retrieval date, a W3C **Working Draft +nearing Candidate Recommendation** (the schema is generated "for MathML4 +drafts"). This snapshot is pinned as retrieved; **re-sync when MathML 4 +reaches CR, and again at REC** (metanorma/metanorma#585 caveat 2). The target +is MathML 4 **full** — not MathML Core, which drops Content MathML. `metanorma-mathml.rnc` is the metanorma wrapper: it `include`s the W3C grammar (`start = math`) and augments it with metanorma's owned extension attributes -(currently `data-metanorma-numberformat` on ``). `basicdoc.rnc` references it -via `mathml = external "mathml/metanorma-mathml.rnc"`, so the wrapper's scope -contains the W3C grammar and avoids any define-name collision with basicdoc. +(currently `data-metanorma-numberformat` on ``), and bans the foreign +markup escape hatches (`annotation-xml`, `anyElement`). `basicdoc.rnc` +references it via `mathml = external "mathml/metanorma-mathml.rnc"`, so the +wrapper's scope contains the W3C grammar and avoids any define-name collision +with basicdoc. Note the documented v4 loosening the wrapper cannot subtract +(embedded XHTML/SVG in token content via `textorHTML`) — see the wrapper's +closing comment and metanorma/basicdoc-models#39. -MathML version is **3** (v4 is not yet officially published). The authoritative -list of `data-metanorma-numberformat` parameters lives in plurimath -(`Formatter::Standard::DEFAULT_OPTIONS`); add new `data-metanorma-*` attributes to -`metanorma-mathml.rnc` as they are coined. See metanorma/basicdoc-models#35. +MathML version is **4** (migrated from 3: metanorma/basicdoc-models#39, +umbrella metanorma/metanorma#585). The authoritative list of +`data-metanorma-numberformat` parameters lives in plurimath +(`Formatter::Standard::DEFAULT_OPTIONS`); add new `data-metanorma-*` +attributes to `metanorma-mathml.rnc` as they are coined. See +metanorma/basicdoc-models#35. diff --git a/grammars/mathml/mathml3-common.rnc b/grammars/mathml/mathml3-common.rnc deleted file mode 100644 index 719f190..0000000 --- a/grammars/mathml/mathml3-common.rnc +++ /dev/null @@ -1,84 +0,0 @@ -# This is the Mathematical Markup Language (MathML) 3.0, an XML -# application for describing mathematical notation and capturing -# both its structure and content. -# -# Copyright 1998-2014 W3C (MIT, ERCIM, Keio, Beihang) -# -# Use and distribution of this code are permitted under the terms -# W3C Software Notice and License -# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - - -default namespace m = "http://www.w3.org/1998/Math/MathML" -namespace local = "" - -start = math - -math = element math {math.attributes,MathExpression*} -MathExpression = semantics - -NonMathMLAtt = attribute (* - (local:*|m:*)) {xsd:string} - -CommonDeprecatedAtt = attribute other {text}? - -CommonAtt = attribute id {xsd:ID}?, - attribute xref {text}?, - attribute class {xsd:NMTOKENS}?, - attribute style {xsd:string}?, - attribute href {xsd:anyURI}?, - CommonDeprecatedAtt, - NonMathMLAtt* - - -math.attributes = CommonAtt, - attribute display {"block" | "inline"}?, - attribute maxwidth {length}?, - attribute overflow {"linebreak" | "scroll" | "elide" | "truncate" | "scale"}?, - attribute altimg {xsd:anyURI}?, - attribute altimg-width {length}?, - attribute altimg-height {length}?, - attribute altimg-valign {length | "top" | "middle" | "bottom"}?, - attribute alttext {text}?, - attribute cdgroup {xsd:anyURI}?, - math.deprecatedattributes - -# the mathml3-presentation schema adds additional attributes -# to the math element, all those valid on mstyle - -math.deprecatedattributes = attribute mode {xsd:string}?, - attribute macros {xsd:string}? - - -name = attribute name {xsd:NCName} -cd = attribute cd {xsd:NCName} - -src = attribute src {xsd:anyURI}? - -annotation = element annotation {annotation.attributes,text} - -annotation-xml.model = (MathExpression|anyElement)* - -anyElement = element (* - m:*) {(attribute * {text}|text| anyElement)*} - -annotation-xml = element annotation-xml {annotation.attributes, - annotation-xml.model} -annotation.attributes = CommonAtt, - cd?, - name?, - DefEncAtt, - src? - -DefEncAtt = attribute encoding {xsd:string}?, - attribute definitionURL {xsd:anyURI}? - -semantics = element semantics {semantics.attributes, - MathExpression, - (annotation|annotation-xml)*} -semantics.attributes = CommonAtt,DefEncAtt,cd?,name? - - - -length = xsd:string { - pattern = '\s*((-?[0-9]*([0-9]\.?|\.[0-9])[0-9]*(e[mx]|in|cm|mm|p[xtc]|%)?)|(negative)?((very){0,2}thi(n|ck)|medium)mathspace)\s*' -} - diff --git a/grammars/mathml/mathml3-presentation.rnc b/grammars/mathml/mathml3-presentation.rnc deleted file mode 100644 index 7606d90..0000000 --- a/grammars/mathml/mathml3-presentation.rnc +++ /dev/null @@ -1,543 +0,0 @@ - -# This is the Mathematical Markup Language (MathML) 3.0, an XML -# application for describing mathematical notation and capturing -# both its structure and content. -# -# Copyright 1998-2014 W3C (MIT, ERCIM, Keio, Beihang) -# -# Use and distribution of this code are permitted under the terms -# W3C Software Notice and License -# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - -default namespace m = "http://www.w3.org/1998/Math/MathML" - -MathExpression |= PresentationExpression - -ImpliedMrow = MathExpression* - -TableRowExpression = mtr|mlabeledtr - -TableCellExpression = mtd - -MstackExpression = MathExpression|mscarries|msline|msrow|msgroup - -MsrowExpression = MathExpression|none - -MultiScriptExpression = (MathExpression|none),(MathExpression|none) - -mpadded-length = xsd:string { - pattern = '\s*([\+\-]?[0-9]*([0-9]\.?|\.[0-9])[0-9]*\s*((%?\s*(height|depth|width)?)|e[mx]|in|cm|mm|p[xtc]|((negative)?((very){0,2}thi(n|ck)|medium)mathspace))?)\s*' } - -linestyle = "none" | "solid" | "dashed" - -verticalalign = - "top" | - "bottom" | - "center" | - "baseline" | - "axis" - -columnalignstyle = "left" | "center" | "right" - -notationstyle = - "longdiv" | - "actuarial" | - "radical" | - "box" | - "roundedbox" | - "circle" | - "left" | - "right" | - "top" | - "bottom" | - "updiagonalstrike" | - "downdiagonalstrike" | - "verticalstrike" | - "horizontalstrike" | - "madruwb" - -idref = text -unsigned-integer = xsd:unsignedLong -integer = xsd:integer -number = xsd:decimal - -character = xsd:string { - pattern = '\s*\S\s*'} - -color = xsd:string { - pattern = '\s*((#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)|[aA][qQ][uU][aA]|[bB][lL][aA][cC][kK]|[bB][lL][uU][eE]|[fF][uU][cC][hH][sS][iI][aA]|[gG][rR][aA][yY]|[gG][rR][eE][eE][nN]|[lL][iI][mM][eE]|[mM][aA][rR][oO][oO][nN]|[nN][aA][vV][yY]|[oO][lL][iI][vV][eE]|[pP][uU][rR][pP][lL][eE]|[rR][eE][dD]|[sS][iI][lL][vV][eE][rR]|[tT][eE][aA][lL]|[wW][hH][iI][tT][eE]|[yY][eE][lL][lL][oO][wW])\s*'} - - -group-alignment = "left" | "center" | "right" | "decimalpoint" -group-alignment-list = list {group-alignment+} -group-alignment-list-list = xsd:string { - pattern = '(\s*\{\s*(left|center|right|decimalpoint)(\s+(left|center|right|decimalpoint))*\})*\s*' } -positive-integer = xsd:positiveInteger - - -TokenExpression = mi|mn|mo|mtext|mspace|ms - -token.content = mglyph|malignmark|text - -mi = element mi {mi.attributes, token.content*} -mi.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt - - -mn = element mn {mn.attributes, token.content*} -mn.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt - - -mo = element mo {mo.attributes, token.content*} -mo.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt, - attribute form {"prefix" | "infix" | "postfix"}?, - attribute fence {"true" | "false"}?, - attribute separator {"true" | "false"}?, - attribute lspace {length}?, - attribute rspace {length}?, - attribute stretchy {"true" | "false"}?, - attribute symmetric {"true" | "false"}?, - attribute maxsize {length | "infinity"}?, - attribute minsize {length}?, - attribute largeop {"true" | "false"}?, - attribute movablelimits {"true" | "false"}?, - attribute accent {"true" | "false"}?, - attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, - attribute lineleading {length}?, - attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, - attribute linebreakmultchar {text}?, - attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, - attribute indentshift {length}?, - attribute indenttarget {idref}?, - attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentshiftfirst {length | "indentshift"}?, - attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentshiftlast {length | "indentshift"}? - - -mtext = element mtext {mtext.attributes, token.content*} -mtext.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt - - -mspace = element mspace {mspace.attributes, empty} -mspace.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt, - attribute width {length}?, - attribute height {length}?, - attribute depth {length}?, - attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak" | "indentingnewline"}?, - attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, - attribute indentshift {length}?, - attribute indenttarget {idref}?, - attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentshiftfirst {length | "indentshift"}?, - attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentshiftlast {length | "indentshift"}? - - -ms = element ms {ms.attributes, token.content*} -ms.attributes = - CommonAtt, - CommonPresAtt, - TokenAtt, - attribute lquote {text}?, - attribute rquote {text}? - - -mglyph = element mglyph {mglyph.attributes,mglyph.deprecatedattributes,empty} -mglyph.attributes = - CommonAtt, CommonPresAtt, - attribute src {xsd:anyURI}?, - attribute width {length}?, - attribute height {length}?, - attribute valign {length}?, - attribute alt {text}? -mglyph.deprecatedattributes = - attribute index {integer}?, - attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, - attribute mathsize {"small" | "normal" | "big" | length}?, - DeprecatedTokenAtt - -msline = element msline {msline.attributes,empty} -msline.attributes = - CommonAtt, CommonPresAtt, - attribute position {integer}?, - attribute length {unsigned-integer}?, - attribute leftoverhang {length}?, - attribute rightoverhang {length}?, - attribute mslinethickness {length | "thin" | "medium" | "thick"}? - -none = element none {none.attributes,empty} -none.attributes = - CommonAtt, - CommonPresAtt - -mprescripts = element mprescripts {mprescripts.attributes,empty} -mprescripts.attributes = - CommonAtt, - CommonPresAtt - - -CommonPresAtt = - attribute mathcolor {color}?, - attribute mathbackground {color | "transparent"}? - -TokenAtt = - attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, - attribute mathsize {"small" | "normal" | "big" | length}?, - attribute dir {"ltr" | "rtl"}?, - DeprecatedTokenAtt - -DeprecatedTokenAtt = - attribute fontfamily {text}?, - attribute fontweight {"normal" | "bold"}?, - attribute fontstyle {"normal" | "italic"}?, - attribute fontsize {length}?, - attribute color {color}?, - attribute background {color | "transparent"}? - -MalignExpression = maligngroup|malignmark - -malignmark = element malignmark {malignmark.attributes, empty} -malignmark.attributes = - CommonAtt, CommonPresAtt, - attribute edge {"left" | "right"}? - - -maligngroup = element maligngroup {maligngroup.attributes, empty} -maligngroup.attributes = - CommonAtt, CommonPresAtt, - attribute groupalign {"left" | "center" | "right" | "decimalpoint"}? - - -PresentationExpression = TokenExpression|MalignExpression| - mrow|mfrac|msqrt|mroot|mstyle|merror|mpadded|mphantom| - mfenced|menclose|msub|msup|msubsup|munder|mover|munderover| - mmultiscripts|mtable|mstack|mlongdiv|maction - - - -mrow = element mrow {mrow.attributes, MathExpression*} -mrow.attributes = - CommonAtt, CommonPresAtt, - attribute dir {"ltr" | "rtl"}? - - -mfrac = element mfrac {mfrac.attributes, MathExpression, MathExpression} -mfrac.attributes = - CommonAtt, CommonPresAtt, - attribute linethickness {length | "thin" | "medium" | "thick"}?, - attribute numalign {"left" | "center" | "right"}?, - attribute denomalign {"left" | "center" | "right"}?, - attribute bevelled {"true" | "false"}? - - -msqrt = element msqrt {msqrt.attributes, ImpliedMrow} -msqrt.attributes = - CommonAtt, CommonPresAtt - - -mroot = element mroot {mroot.attributes, MathExpression, MathExpression} -mroot.attributes = - CommonAtt, CommonPresAtt - - -mstyle = element mstyle {mstyle.attributes, ImpliedMrow} -mstyle.attributes = - CommonAtt, CommonPresAtt, - mstyle.specificattributes, - mstyle.generalattributes, - mstyle.deprecatedattributes - -mstyle.specificattributes = - attribute scriptlevel {integer}?, - attribute displaystyle {"true" | "false"}?, - attribute scriptsizemultiplier {number}?, - attribute scriptminsize {length}?, - attribute infixlinebreakstyle {"before" | "after" | "duplicate"}?, - attribute decimalpoint {character}? - -mstyle.generalattributes = - attribute accent {"true" | "false"}?, - attribute accentunder {"true" | "false"}?, - attribute align {"left" | "right" | "center"}?, - attribute alignmentscope {list {("true" | "false") +}}?, - attribute bevelled {"true" | "false"}?, - attribute charalign {"left" | "center" | "right"}?, - attribute charspacing {length | "loose" | "medium" | "tight"}?, - attribute close {text}?, - attribute columnalign {list {columnalignstyle+} }?, - attribute columnlines {list {linestyle +}}?, - attribute columnspacing {list {(length) +}}?, - attribute columnspan {positive-integer}?, - attribute columnwidth {list {("auto" | length | "fit") +}}?, - attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, - attribute denomalign {"left" | "center" | "right"}?, - attribute depth {length}?, - attribute dir {"ltr" | "rtl"}?, - attribute edge {"left" | "right"}?, - attribute equalcolumns {"true" | "false"}?, - attribute equalrows {"true" | "false"}?, - attribute fence {"true" | "false"}?, - attribute form {"prefix" | "infix" | "postfix"}?, - attribute frame {linestyle}?, - attribute framespacing {list {length, length}}?, - attribute groupalign {group-alignment-list-list}?, - attribute height {length}?, - attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, - attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, - attribute indentshift {length}?, - attribute indentshiftfirst {length | "indentshift"}?, - attribute indentshiftlast {length | "indentshift"}?, - attribute indenttarget {idref}?, - attribute largeop {"true" | "false"}?, - attribute leftoverhang {length}?, - attribute length {unsigned-integer}?, - attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, - attribute linebreakmultchar {text}?, - attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, - attribute lineleading {length}?, - attribute linethickness {length | "thin" | "medium" | "thick"}?, - attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, - attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}?, - attribute lquote {text}?, - attribute lspace {length}?, - attribute mathsize {"small" | "normal" | "big" | length}?, - attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?, - attribute maxsize {length | "infinity"}?, - attribute minlabelspacing {length}?, - attribute minsize {length}?, - attribute movablelimits {"true" | "false"}?, - attribute mslinethickness {length | "thin" | "medium" | "thick"}?, - attribute notation {text}?, - attribute numalign {"left" | "center" | "right"}?, - attribute open {text}?, - attribute position {integer}?, - attribute rightoverhang {length}?, - attribute rowalign {list {verticalalign+} }?, - attribute rowlines {list {linestyle +}}?, - attribute rowspacing {list {(length) +}}?, - attribute rowspan {positive-integer}?, - attribute rquote {text}?, - attribute rspace {length}?, - attribute selection {positive-integer}?, - attribute separator {"true" | "false"}?, - attribute separators {text}?, - attribute shift {integer}?, - attribute side {"left" | "right" | "leftoverlap" | "rightoverlap"}?, - attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?, - attribute stretchy {"true" | "false"}?, - attribute subscriptshift {length}?, - attribute superscriptshift {length}?, - attribute symmetric {"true" | "false"}?, - attribute valign {length}?, - attribute width {length}? - -mstyle.deprecatedattributes = - DeprecatedTokenAtt, - attribute veryverythinmathspace {length}?, - attribute verythinmathspace {length}?, - attribute thinmathspace {length}?, - attribute mediummathspace {length}?, - attribute thickmathspace {length}?, - attribute verythickmathspace {length}?, - attribute veryverythickmathspace {length}? - -math.attributes &= CommonPresAtt -math.attributes &= mstyle.specificattributes -math.attributes &= mstyle.generalattributes - - - - -merror = element merror {merror.attributes, ImpliedMrow} -merror.attributes = - CommonAtt, CommonPresAtt - - -mpadded = element mpadded {mpadded.attributes, ImpliedMrow} -mpadded.attributes = - CommonAtt, CommonPresAtt, - attribute height {mpadded-length}?, - attribute depth {mpadded-length}?, - attribute width {mpadded-length}?, - attribute lspace {mpadded-length}?, - attribute voffset {mpadded-length}? - - -mphantom = element mphantom {mphantom.attributes, ImpliedMrow} -mphantom.attributes = - CommonAtt, CommonPresAtt - - -mfenced = element mfenced {mfenced.attributes, MathExpression*} -mfenced.attributes = - CommonAtt, CommonPresAtt, - attribute open {text}?, - attribute close {text}?, - attribute separators {text}? - - -menclose = element menclose {menclose.attributes, ImpliedMrow} -menclose.attributes = - CommonAtt, CommonPresAtt, - attribute notation {text}? - - -msub = element msub {msub.attributes, MathExpression, MathExpression} -msub.attributes = - CommonAtt, CommonPresAtt, - attribute subscriptshift {length}? - - -msup = element msup {msup.attributes, MathExpression, MathExpression} -msup.attributes = - CommonAtt, CommonPresAtt, - attribute superscriptshift {length}? - - -msubsup = element msubsup {msubsup.attributes, MathExpression, MathExpression, MathExpression} -msubsup.attributes = - CommonAtt, CommonPresAtt, - attribute subscriptshift {length}?, - attribute superscriptshift {length}? - - -munder = element munder {munder.attributes, MathExpression, MathExpression} -munder.attributes = - CommonAtt, CommonPresAtt, - attribute accentunder {"true" | "false"}?, - attribute align {"left" | "right" | "center"}? - - -mover = element mover {mover.attributes, MathExpression, MathExpression} -mover.attributes = - CommonAtt, CommonPresAtt, - attribute accent {"true" | "false"}?, - attribute align {"left" | "right" | "center"}? - - -munderover = element munderover {munderover.attributes, MathExpression, MathExpression, MathExpression} -munderover.attributes = - CommonAtt, CommonPresAtt, - attribute accent {"true" | "false"}?, - attribute accentunder {"true" | "false"}?, - attribute align {"left" | "right" | "center"}? - - -mmultiscripts = element mmultiscripts {mmultiscripts.attributes, MathExpression,MultiScriptExpression*,(mprescripts,MultiScriptExpression*)?} -mmultiscripts.attributes = - msubsup.attributes - - -mtable = element mtable {mtable.attributes, TableRowExpression*} -mtable.attributes = - CommonAtt, CommonPresAtt, - attribute align {xsd:string { - pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?, - attribute rowalign {list {verticalalign+} }?, - attribute columnalign {list {columnalignstyle+} }?, - attribute groupalign {group-alignment-list-list}?, - attribute alignmentscope {list {("true" | "false") +}}?, - attribute columnwidth {list {("auto" | length | "fit") +}}?, - attribute width {"auto" | length}?, - attribute rowspacing {list {(length) +}}?, - attribute columnspacing {list {(length) +}}?, - attribute rowlines {list {linestyle +}}?, - attribute columnlines {list {linestyle +}}?, - attribute frame {linestyle}?, - attribute framespacing {list {length, length}}?, - attribute equalrows {"true" | "false"}?, - attribute equalcolumns {"true" | "false"}?, - attribute displaystyle {"true" | "false"}?, - attribute side {"left" | "right" | "leftoverlap" | "rightoverlap"}?, - attribute minlabelspacing {length}? - - -mlabeledtr = element mlabeledtr {mlabeledtr.attributes, TableCellExpression+} -mlabeledtr.attributes = - mtr.attributes - - -mtr = element mtr {mtr.attributes, TableCellExpression*} -mtr.attributes = - CommonAtt, CommonPresAtt, - attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?, - attribute columnalign {list {columnalignstyle+} }?, - attribute groupalign {group-alignment-list-list}? - - -mtd = element mtd {mtd.attributes, ImpliedMrow} -mtd.attributes = - CommonAtt, CommonPresAtt, - attribute rowspan {positive-integer}?, - attribute columnspan {positive-integer}?, - attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?, - attribute columnalign {columnalignstyle}?, - attribute groupalign {group-alignment-list}? - - -mstack = element mstack {mstack.attributes, MstackExpression*} -mstack.attributes = - CommonAtt, CommonPresAtt, - attribute align {xsd:string { - pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?, - attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?, - attribute charalign {"left" | "center" | "right"}?, - attribute charspacing {length | "loose" | "medium" | "tight"}? - - -mlongdiv = element mlongdiv {mlongdiv.attributes, MstackExpression,MstackExpression,MstackExpression+} -mlongdiv.attributes = - msgroup.attributes, - attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}? - - -msgroup = element msgroup {msgroup.attributes, MstackExpression*} -msgroup.attributes = - CommonAtt, CommonPresAtt, - attribute position {integer}?, - attribute shift {integer}? - - -msrow = element msrow {msrow.attributes, MsrowExpression*} -msrow.attributes = - CommonAtt, CommonPresAtt, - attribute position {integer}? - - -mscarries = element mscarries {mscarries.attributes, (MsrowExpression|mscarry)*} -mscarries.attributes = - CommonAtt, CommonPresAtt, - attribute position {integer}?, - attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, - attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, - attribute scriptsizemultiplier {number}? - - -mscarry = element mscarry {mscarry.attributes, MsrowExpression*} -mscarry.attributes = - CommonAtt, CommonPresAtt, - attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, - attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}? - - -maction = element maction {maction.attributes, MathExpression+} -maction.attributes = - CommonAtt, CommonPresAtt, - attribute actiontype {text}, - attribute selection {positive-integer}? diff --git a/grammars/mathml/mathml3-strict-content.rnc b/grammars/mathml/mathml3-strict-content.rnc deleted file mode 100644 index dce0422..0000000 --- a/grammars/mathml/mathml3-strict-content.rnc +++ /dev/null @@ -1,60 +0,0 @@ -# This is the Mathematical Markup Language (MathML) 3.0, an XML -# application for describing mathematical notation and capturing -# both its structure and content. -# -# Copyright 1998-2014 W3C (MIT, ERCIM, Keio, Beihang) -# -# Use and distribution of this code are permitted under the terms -# W3C Software Notice and License -# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - - -default namespace m = "http://www.w3.org/1998/Math/MathML" - -ContExp = semantics-contexp | cn | ci | csymbol | apply | bind | share | cerror | cbytes | cs - -cn = element cn {cn.attributes,cn.content} -cn.content = text -cn.attributes = CommonAtt, attribute type {"integer" | "real" | "double" | "hexdouble"} - -semantics-ci = element semantics {semantics.attributes,(ci|semantics-ci), - (annotation|annotation-xml)*} - -semantics-contexp = element semantics {semantics.attributes,ContExp, - (annotation|annotation-xml)*} - -ci = element ci {ci.attributes, ci.content} -ci.attributes = CommonAtt, ci.type? -ci.type = attribute type {"integer" | "rational" | "real" | "complex" | "complex-polar" | "complex-cartesian" | "constant" | "function" | "vector" | "list" | "set" | "matrix"} -ci.content = text - - -csymbol = element csymbol {csymbol.attributes,csymbol.content} - -SymbolName = xsd:NCName -csymbol.attributes = CommonAtt, cd -csymbol.content = SymbolName - -BvarQ = bvar* -bvar = element bvar {CommonAtt, (ci | semantics-ci)} - -apply = element apply {CommonAtt,apply.content} -apply.content = ContExp+ - - -bind = element bind {CommonAtt,bind.content} -bind.content = ContExp,bvar*,ContExp - -share = element share {CommonAtt, src, empty} - -cerror = element cerror {cerror.attributes, csymbol, ContExp*} -cerror.attributes = CommonAtt - -cbytes = element cbytes {cbytes.attributes, base64} -cbytes.attributes = CommonAtt -base64 = xsd:base64Binary - -cs = element cs {cs.attributes, text} -cs.attributes = CommonAtt - -MathExpression |= ContExp diff --git a/grammars/mathml/mathml3.rnc b/grammars/mathml/mathml3.rnc deleted file mode 100644 index 3c68cdb..0000000 --- a/grammars/mathml/mathml3.rnc +++ /dev/null @@ -1,21 +0,0 @@ -# This is the Mathematical Markup Language (MathML) 3.0, an XML -# application for describing mathematical notation and capturing -# both its structure and content. -# -# Copyright 1998-2010 W3C (MIT, ERCIM, Keio) -# -# Use and distribution of this code are permitted under the terms -# W3C Software Notice and License -# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - - -default namespace m = "http://www.w3.org/1998/Math/MathML" - -## Content MathML -include "mathml3-content.rnc" - -## Presentation MathML -include "mathml3-presentation.rnc" - -## math and semantics common to both Content and Presentation -include "mathml3-common.rnc" diff --git a/grammars/mathml/mathml3-content.rnc b/grammars/mathml/mathml4-content.rnc similarity index 86% rename from grammars/mathml/mathml3-content.rnc rename to grammars/mathml/mathml4-content.rnc index 9603ed4..233abcd 100644 --- a/grammars/mathml/mathml3-content.rnc +++ b/grammars/mathml/mathml4-content.rnc @@ -1,24 +1,27 @@ +# MathML 4 (Content) +# ################## -# This is the Mathematical Markup Language (MathML) 3.0, an XML -# application for describing mathematical notation and capturing -# both its structure and content. -# -# Copyright 1998-2014 W3C (MIT, ERCIM, Keio, Beihang) +# Copyright 1998-2026 W3C (MIT, ERCIM, Keio, Beihang) # # Use and distribution of this code are permitted under the terms # W3C Software Notice and License # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 -include "mathml3-strict-content.rnc"{ - cn.content = (text | mglyph | sep | PresentationExpression)* +default namespace m = "http://www.w3.org/1998/Math/MathML" +namespace local = "" + +include "mathml4-strict-content.rnc"{ + cn.content = (text | sep | PresentationExpression)* cn.attributes = CommonAtt, DefEncAtt, attribute type {text}?, base? ci.attributes = CommonAtt, DefEncAtt, ci.type? ci.type = attribute type {text} - ci.content = (text | mglyph | PresentationExpression)* + ci.content = (text | PresentationExpression)* csymbol.attributes = CommonAtt, DefEncAtt, attribute type {text}?,cd? - csymbol.content = (text | mglyph | PresentationExpression)* + csymbol.content = (text | PresentationExpression)* + + annotation-xml.attributes |= CommonAtt, cd?, name?, encoding? bvar = element bvar {CommonAtt, ((ci | semantics-ci) & degree?)} @@ -31,11 +34,39 @@ include "mathml3-strict-content.rnc"{ bind.content = apply.content } +NonMathMLAtt |= attribute (* - (local:*|m:*)) {xsd:string} + +# METANORMA MODIFICATION (basicdoc-models#39): upstream re-adds +# `attribute alttext` to math.attributes here, but mathml4-core.rnc already +# defines it on math; RELAX NG's duplicate-attribute restriction rejects the +# composed grammar (jing: 'duplicate attribute "alttext"'). +# Upstream text was: +# math.attributes &= +# attribute alttext {text}? + +# METANORMA MODIFICATION (basicdoc-models#39): upstream re-adds the +# `data-other` placeholder to MathMLDataAttributes here; dropped for the +# same reason as the core placeholder (see mathml4-core.rnc modification). +# Upstream text was: +# MathMLDataAttributes &= +# attribute data-other {text}? + +CommonAtt &= + NonMathMLAtt*, + MathMLDataAttributes, + attribute class {xsd:NCName}?, + attribute style {xsd:string}?, + attribute href {xsd:anyURI}?, + attribute intent {text}?, + attribute arg {xsd:NCName}? + base = attribute base {text} sep = element sep {empty} PresentationExpression |= notAllowed +DefEncAtt = attribute encoding {xsd:string}?, + attribute definitionURL {xsd:anyURI}? DomainQ = (domainofapplication|condition|interval|(lowlimit,uplimit?))* @@ -64,19 +95,6 @@ piece = element piece {CommonAtt, DefEncAtt, ContExp, ContExp} otherwise = element otherwise {CommonAtt, DefEncAtt, ContExp} -DeprecatedContExp = reln | fn | declare -ContExp |= DeprecatedContExp - -reln = element reln {ContExp*} -fn = element fn {ContExp} -declare = element declare {attribute type {xsd:string}?, - attribute scope {xsd:string}?, - attribute nargs {xsd:nonNegativeInteger}?, - attribute occurrence {"prefix"|"infix"|"function-model"}?, - DefEncAtt, - ContExp+} - - interval.class = interval ContExp |= interval.class @@ -308,15 +326,15 @@ arcsech = element arcsech { CommonAtt, DefEncAtt, empty} arcsinh = element arcsinh { CommonAtt, DefEncAtt, empty} arctanh = element arctanh { CommonAtt, DefEncAtt, empty} -nary-stats.class = mean | sdev | variance | median | mode +nary-stats.class = mean | median | mode | sdev | variance ContExp |= nary-stats.class mean = element mean { CommonAtt, DefEncAtt, empty} -sdev = element sdev { CommonAtt, DefEncAtt, empty} -variance = element variance { CommonAtt, DefEncAtt, empty} median = element median { CommonAtt, DefEncAtt, empty} mode = element mode { CommonAtt, DefEncAtt, empty} +sdev = element sdev { CommonAtt, DefEncAtt, empty} +variance = element variance { CommonAtt, DefEncAtt, empty} nary-constructor.class = vector | matrix | matrixrow ContExp |= nary-constructor.class @@ -370,4 +388,4 @@ true = element true { CommonAtt, DefEncAtt, empty} false = element false { CommonAtt, DefEncAtt, empty} pi = element pi { CommonAtt, DefEncAtt, empty} eulergamma = element eulergamma { CommonAtt, DefEncAtt, empty} -infinity = element infinity { CommonAtt, DefEncAtt, empty} \ No newline at end of file +infinity = element infinity { CommonAtt, DefEncAtt, empty} diff --git a/grammars/mathml/mathml4-core.rnc b/grammars/mathml/mathml4-core.rnc new file mode 100644 index 0000000..801aa62 --- /dev/null +++ b/grammars/mathml/mathml4-core.rnc @@ -0,0 +1,394 @@ +# MathML 4 (Core Level 1) +# ####################### + +# Copyright 1998-2026 W3C (MIT, ERCIM, Keio, Beihang) +# +# Use and distribution of this code are permitted under the terms +# W3C Software Notice and License +# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +default namespace m = "http://www.w3.org/1998/Math/MathML" +namespace h = "http://www.w3.org/1999/xhtml" +namespace svg = "http://www.w3.org/2000/svg" + +start |= math + +math = element math {math.attributes,ImpliedMrow} + +MathMLoneventAttributes = + attribute onabort {text}?, + attribute onauxclick {text}?, + attribute onblur {text}?, + attribute oncancel {text}?, + attribute oncanplay {text}?, + attribute oncanplaythrough {text}?, + attribute onchange {text}?, + attribute onclick {text}?, + attribute onclose {text}?, + attribute oncontextlost {text}?, + attribute oncontextmenu {text}?, + attribute oncontextrestored {text}?, + attribute oncuechange {text}?, + attribute ondblclick {text}?, + attribute ondrag {text}?, + attribute ondragend {text}?, + attribute ondragenter {text}?, + attribute ondragleave {text}?, + attribute ondragover {text}?, + attribute ondragstart {text}?, + attribute ondrop {text}?, + attribute ondurationchange {text}?, + attribute onemptied {text}?, + attribute onended {text}?, + attribute onerror {text}?, + attribute onfocus {text}?, + attribute onformdata {text}?, + attribute oninput {text}?, + attribute oninvalid {text}?, + attribute onkeydown {text}?, + attribute onkeypress {text}?, + attribute onkeyup {text}?, + attribute onload {text}?, + attribute onloadeddata {text}?, + attribute onloadedmetadata {text}?, + attribute onloadstart {text}?, + attribute onmousedown {text}?, + attribute onmouseenter {text}?, + attribute onmouseleave {text}?, + attribute onmousemove {text}?, + attribute onmouseout {text}?, + attribute onmouseover {text}?, + attribute onmouseup {text}?, + attribute onpause {text}?, + attribute onplay {text}?, + attribute onplaying {text}?, + attribute onprogress {text}?, + attribute onratechange {text}?, + attribute onreset {text}?, + attribute onresize {text}?, + attribute onscroll {text}?, + attribute onsecuritypolicyviolation {text}?, + attribute onseeked {text}?, + attribute onseeking {text}?, + attribute onselect {text}?, + attribute onslotchange {text}?, + attribute onstalled {text}?, + attribute onsubmit {text}?, + attribute onsuspend {text}?, + attribute ontimeupdate {text}?, + attribute ontoggle {text}?, + attribute onvolumechange {text}?, + attribute onwaiting {text}?, + attribute onwebkitanimationend {text}?, + attribute onwebkitanimationiteration {text}?, + attribute onwebkitanimationstart {text}?, + attribute onwebkittransitionend {text}?, + attribute onwheel {text}?, + attribute onafterprint {text}?, + attribute onbeforeprint {text}?, + attribute onbeforeunload {text}?, + attribute onhashchange {text}?, + attribute onlanguagechange {text}?, + attribute onmessage {text}?, + attribute onmessageerror {text}?, + attribute onoffline {text}?, + attribute ononline {text}?, + attribute onpagehide {text}?, + attribute onpageshow {text}?, + attribute onpopstate {text}?, + attribute onrejectionhandled {text}?, + attribute onstorage {text}?, + attribute onunhandledrejection {text}?, + attribute onunload {text}?, + attribute oncopy {text}?, + attribute oncut {text}?, + attribute onpaste {text}? + +MathMLlink.attributes= + attribute attributionsrc {text}?, + attribute download {mathml-boolean}?, + attribute filename {text}?, + # METANORMA MODIFICATION (basicdoc-models#39): `attribute href` removed + # here — the full profile adds href to MathMLPGlobalAttributes + # (mathml4-presentation.rnc), so the element (mrow.attributes + + # MathMLlink.attributes) would carry it twice, which RELAX NG's + # duplicate-attribute restriction forbids (jing: 'duplicate attribute + # "href"'). href remains available on via the global set. + attribute hreflang {text}?, + attribute referrerpolicy {text}?, + attribute rel {text}?, + attribute target {text}?, + attribute type {text}? + + + +# Sample set. May need preprocessing +# or schema extension to allow more see MathML Core (and HTML) spec +MathMLDataAttributes = + # METANORMA MODIFICATION (basicdoc-models#39): upstream places a literal + # `attribute data-other {text}?` here as an admitted placeholder for + # data-* ("Sample set. May need preprocessing"). In the full-MathML + # profile it duplicates the NonMathMLAtt any-attribute wildcard + # (mathml4-presentation.rnc), which RELAX NG forbids (jing: 'duplicate + # attribute "data-other"'). The wildcard subsumes data-*; the literal is + # dropped. + empty + + +# sample set, like data- may need preprocessing to allow more +MathMLARIAattributes = + attribute aria-label {text}?, + attribute aria-describedby {text}?, + attribute aria-description {text}?, + attribute aria-details {text}? + +MathMLintentAttributes = + attribute intent {text}?, + attribute arg {xsd:NCName}? + +MathMLPGlobalAttributes = attribute id {xsd:ID}?, + attribute class {xsd:NCName}?, + attribute style {xsd:string}?, + attribute dir {"ltr" | "rtl"}?, + attribute mathbackground {color}?, + attribute mathcolor {color}?, + attribute mathsize {length-percentage}?, + attribute mathvariant {xsd:string{pattern="\s*([Nn][Oo][Rr][Mm][Aa][Ll]|[Bb][Oo][Ll][Dd]|[Ii][Tt][Aa][Ll][Ii][Cc]|[Bb][Oo][Ll][Dd]-[Ii][Tt][Aa][Ll][Ii][Cc]|[Dd][Oo][Uu][Bb][Ll][Ee]-[Ss][Tt][Rr][Uu][Cc][Kk]|[Bb][Oo][Ll][Dd]-[Ff][Rr][Aa][Kk][Tt][Uu][Rr]|[Ss][Cc][Rr][Ii][Pp][Tt]|[Bb][Oo][Ll][Dd]-[Ss][Cc][Rr][Ii][Pp][Tt]|[Ff][Rr][Aa][Kk][Tt][Uu][Rr]|[Ss][Aa][Nn][Ss]-[Ss][Ee][Rr][Ii][Ff]|[Bb][Oo][Ll][Dd]-[Ss][Aa][Nn][Ss]-[Ss][Ee][Rr][Ii][Ff]|[Ss][Aa][Nn][Ss]-[Ss][Ee][Rr][Ii][Ff]-[Ii][Tt][Aa][Ll][Ii][Cc]|[Ss][Aa][Nn][Ss]-[Ss][Ee][Rr][Ii][Ff]-[Bb][Oo][Ll][Dd]-[Ii][Tt][Aa][Ll][Ii][Cc]|[Mm][Oo][Nn][Oo][Ss][Pp][Aa][Cc][Ee]|[Ii][Nn][Ii][Tt][Ii][Aa][Ll]|[Tt][Aa][Ii][Ll][Ee][Dd]|[Ll][Oo][Oo][Pp][Ee][Dd]|[Ss][Tt][Rr][Ee][Tt][Cc][Hh][Ee][Dd])\s*"}}?, + attribute displaystyle {mathml-boolean}?, + attribute scriptlevel {xsd:integer}?, + attribute autofocus {mathml-boolean}?, + attribute tabindex {xsd:integer}?, + attribute nonce {text}?, + MathMLoneventAttributes, + # Extension attributes, no defined behavior + MathMLDataAttributes, + # No specified behavior in Core, see MathML4 + MathMLintentAttributes, + # No specified behavior in Core, see WAI-ARIA + MathMLARIAattributes + + + +math.attributes = MathMLPGlobalAttributes, + attribute display {"block" | "inline"}?, + # No specified behavior in Core, see MathML4 + attribute alttext {text}? + + +annotation = element annotation {MathMLPGlobalAttributes,encoding?,text} + +anyElement = element (*) {(attribute * {text}|text| anyElement)*} + +annotation-xml = element annotation-xml {annotation-xml.attributes, + (MathExpression*|anyElement*)} + +annotation-xml.attributes = MathMLPGlobalAttributes, encoding? + +encoding=attribute encoding {xsd:string}? + + +semantics = element semantics {semantics.attributes, + MathExpression, + (annotation|annotation-xml)*} + +semantics.attributes = MathMLPGlobalAttributes + +mathml-boolean = xsd:string { + pattern = '\s*([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])\s*' +} + +length-percentage = xsd:string { + pattern = '\s*((-?[0-9]*([0-9]\.?|\.[0-9])[0-9]*(r?em|ex|in|cm|mm|p[xtc]|Q|v[hw]|vmin|vmax|%))|0)\s*' +} + +MathExpression = TokenExpression| + mrow|a|mfrac|msqrt|mroot|mstyle|merror|mpadded|mphantom| + msub|msup|msubsup|munder|mover|munderover| + mmultiscripts|mtable|maction| + semantics + +MathMalignExpression = MathExpression + +ImpliedMrow = MathMalignExpression* + +TableRowExpression = mtr + +MultiScriptExpression = (MathExpression|none),(MathExpression|none) + + +color = xsd:string { + pattern = '\s*((#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)|[a-zA-Z]+|[a-zA-Z]+\s*\([0-9, %.]+\))\s*'} + +TokenExpression = mi|mn|mo|mtext|mspace|ms + + +# METANORMA MODIFICATION (basicdoc-models#39): upstream admits embedded +# XHTML (h:*) and svg:svg inside token elements. libxml2's RELAX NG rejects +# the compiled grammar outright on the svg branch ("Element svg attributes +# have a content type error", wildcard-attribute constructs), which breaks +# every passthrough validation in metanorma-standoc; and metanorma's +# serialiser never emits embedded HTML/SVG in math tokens (the wrapper bans +# foreign markup generally). Both foreign branches are removed. +# Upstream text was: +# textorHTML = text | math | element (h:*) {attribute * {text}*,(textorHTML)*} | element svg:svg {attribute * {text}*, anyElement*} +textorHTML = text | math + +token.content = (textorHTML)* + +mi = element mi {mi.attributes, token.content} +mi.attributes = + MathMLPGlobalAttributes + +mn = element mn {mn.attributes, token.content} +mn.attributes = + MathMLPGlobalAttributes + +mo = element mo {mo.attributes, token.content} +mo.attributes = + MathMLPGlobalAttributes, + attribute form {"prefix" | "infix" | "postfix"}?, + attribute lspace {length-percentage}?, + attribute rspace {length-percentage}?, + attribute stretchy {mathml-boolean}?, + attribute symmetric {mathml-boolean}?, + # METANORMA MODIFICATION (basicdoc-models#39): value space merged with the + # presentation profile's `maxsize {"infinity"}` re-declaration, which RELAX + # NG's duplicate-attribute restriction forbids as a separate attribute. + attribute maxsize {length-percentage | "infinity"}?, + attribute minsize {length-percentage}?, + attribute largeop {mathml-boolean}?, + attribute movablelimits {mathml-boolean}? + + +mtext = element mtext {mtext.attributes, token.content} +mtext.attributes = + MathMLPGlobalAttributes + +mspace = element mspace {mspace.attributes, empty} +mspace.attributes = + MathMLPGlobalAttributes, + attribute width {length-percentage}?, + attribute height {length-percentage}?, + attribute depth {length-percentage}? + +ms = element ms {ms.attributes, token.content} +ms.attributes = + MathMLPGlobalAttributes + + +none = element none {none.attributes,empty} +none.attributes = + MathMLPGlobalAttributes + +mprescripts = element mprescripts {mprescripts.attributes,empty} +mprescripts.attributes = + MathMLPGlobalAttributes + +mrow = element mrow {mrow.attributes, ImpliedMrow} +mrow.attributes = + MathMLPGlobalAttributes + +# METANORMA MODIFICATION (basicdoc-models#39): upstream composes +# `mrow.attributes, MathMLlink.attributes` on , but the full profile +# already augments mrow.attributes with MathMLlink.attributes +# (mathml4-presentation.rnc), so every link attribute would appear twice on +# , which RELAX NG's duplicate-attribute restriction forbids (jing: +# 'duplicate attribute "attributionsrc"'). +# Upstream text was: +# a = element a {mrow.attributes, MathMLlink.attributes, ImpliedMrow} +a = element a {mrow.attributes, ImpliedMrow} + +mfrac = element mfrac {mfrac.attributes, MathExpression, MathExpression} +mfrac.attributes = + MathMLPGlobalAttributes, + attribute linethickness {length-percentage}? + +msqrt = element msqrt {msqrt.attributes, ImpliedMrow} +msqrt.attributes = + MathMLPGlobalAttributes + +mroot = element mroot {mroot.attributes, MathExpression, MathExpression} +mroot.attributes = + MathMLPGlobalAttributes + +mstyle = element mstyle {mstyle.attributes, ImpliedMrow} +mstyle.attributes = + MathMLPGlobalAttributes + +merror = element merror {merror.attributes, ImpliedMrow} +merror.attributes = + MathMLPGlobalAttributes + +mpadded = element mpadded {mpadded.attributes, ImpliedMrow} +mpadded.attributes = + MathMLPGlobalAttributes, + attribute height {mpadded-length-percentage}?, + attribute depth {mpadded-length-percentage}?, + attribute width {mpadded-length-percentage}?, + attribute lspace {mpadded-length-percentage}?, + attribute rspace {mpadded-length-percentage}?, + attribute voffset {mpadded-length-percentage}? + +mpadded-length-percentage=length-percentage + +mphantom = element mphantom {mphantom.attributes, ImpliedMrow} +mphantom.attributes = + MathMLPGlobalAttributes + + +msub = element msub {msub.attributes, MathExpression, MathExpression} +msub.attributes = + MathMLPGlobalAttributes + +msup = element msup {msup.attributes, MathExpression, MathExpression} +msup.attributes = + MathMLPGlobalAttributes + +msubsup = element msubsup {msubsup.attributes, MathExpression, MathExpression, MathExpression} +msubsup.attributes = + MathMLPGlobalAttributes + +munder = element munder {munder.attributes, MathExpression, MathExpression} +munder.attributes = + MathMLPGlobalAttributes, + attribute accentunder {mathml-boolean}? + +mover = element mover {mover.attributes, MathExpression, MathExpression} +mover.attributes = + MathMLPGlobalAttributes, + attribute accent {mathml-boolean}? + +munderover = element munderover {munderover.attributes, MathExpression, MathExpression, MathExpression} +munderover.attributes = + MathMLPGlobalAttributes, + attribute accent {mathml-boolean}?, + attribute accentunder {mathml-boolean}? + +mmultiscripts = element mmultiscripts {mmultiscripts.attributes, + MathExpression, + MultiScriptExpression*, + (mprescripts,MultiScriptExpression*)?} +mmultiscripts.attributes = + msubsup.attributes + +mtable = element mtable {mtable.attributes, TableRowExpression*} +mtable.attributes = + MathMLPGlobalAttributes + + +mtr = element mtr {mtr.attributes, mtd*} +mtr.attributes = + MathMLPGlobalAttributes + +mtd = element mtd {mtd.attributes, ImpliedMrow} +mtd.attributes = + MathMLPGlobalAttributes, + attribute rowspan {xsd:positiveInteger}?, + attribute columnspan {xsd:positiveInteger}? + + +maction = element maction {maction.attributes, ImpliedMrow} +maction.attributes = + MathMLPGlobalAttributes, + attribute actiontype {text}?, + attribute selection {xsd:positiveInteger}? diff --git a/grammars/mathml/mathml4-presentation.rnc b/grammars/mathml/mathml4-presentation.rnc new file mode 100644 index 0000000..a4bedf5 --- /dev/null +++ b/grammars/mathml/mathml4-presentation.rnc @@ -0,0 +1,369 @@ +# MathML 4 (Presentation) +# ####################### + +# Copyright 1998-2026 W3C (MIT, ERCIM, Keio, Beihang) +# +# Use and distribution of this code are permitted under the terms +# W3C Software Notice and License +# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +default namespace m = "http://www.w3.org/1998/Math/MathML" +namespace local = "" + + +# MathML Core +include "mathml4-core.rnc" { + +# named lengths +length-percentage = xsd:string { + pattern = '\s*((-?[0-9]*([0-9]\.?|\.[0-9])[0-9]*(r?em|ex|in|cm|mm|p[xtc]|Q|v[hw]|vmin|vmax|%))|0|(negative)?((very){0,2}thi(n|ck)|medium)mathspace)\s*' +} + +mpadded-length-percentage = xsd:string { + pattern = '\s*([\+\-]?[0-9]*([0-9]\.?|\.[0-9])[0-9]*\s*((%?\s*(height|depth|width)?)|r?em|ex|in|cm|mm|p[xtc]|Q|v[hw]|vmin|vmax|%|((negative)?((very){0,2}thi(n|ck)|medium)mathspace))?)\s*' +} + + +} + +NonMathMLAtt = attribute (* - (local:* | m:*)) {xsd:string} + +MathMLPGlobalAttributes &= + NonMathMLAtt*, + attribute xref {text}?, + attribute href {xsd:anyURI}? + +MathMalignExpression |= MalignExpression + +MathExpression |= PresentationExpression + +MstackExpression = MathMalignExpression|mscarries|msline|msrow|msgroup + +MsrowExpression = MathMalignExpression|none + + +linestyle = "none" | "solid" | "dashed" + +verticalalign = + "top" | + "bottom" | + "center" | + "baseline" | + "axis" + +columnalignstyle = "left" | "center" | "right" + +notationstyle = + "longdiv" | + "actuarial" | + "radical" | + "box" | + "roundedbox" | + "circle" | + "left" | + "right" | + "top" | + "bottom" | + "updiagonalstrike" | + "downdiagonalstrike" | + "verticalstrike" | + "horizontalstrike" | + "madruwb" + +idref = text +unsigned-integer = xsd:unsignedLong +integer = xsd:integer +number = xsd:decimal + +character = xsd:string { + pattern = '\s*\S\s*'} + + +positive-integer = xsd:positiveInteger + + +token.content |= mglyph|text + + + +mo.attributes &= + attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, + attribute lineleading {length-percentage}?, + attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, + attribute linebreakmultchar {text}?, + attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, + attribute indentshift {length-percentage}?, + attribute indenttarget {idref}?, + attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentshiftfirst {length-percentage | "indentshift"}?, + attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentshiftlast {length-percentage | "indentshift"}?, + attribute accent {mathml-boolean}? + # METANORMA MODIFICATION (basicdoc-models#39): upstream re-declared + # `attribute maxsize {"infinity"}?` here to extend the core value space; + # RELAX NG forbids duplicate attributes, so "infinity" is merged into the + # core declaration (mathml4-core.rnc mo.attributes) instead. + + +mspace.attributes &= + attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak" | "indentingnewline"}?, + attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, + attribute indentshift {length-percentage}?, + attribute indenttarget {idref}?, + attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentshiftfirst {length-percentage | "indentshift"}?, + attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentshiftlast {length-percentage | "indentshift"}? + + +ms.attributes &= + attribute lquote {text}?, + attribute rquote {text}? + + +mglyph = element mglyph {mglyph.attributes,empty} +mglyph.attributes = + MathMLPGlobalAttributes, + attribute src {xsd:anyURI}?, + attribute width {length-percentage}?, + attribute height {length-percentage}?, + attribute valign {length-percentage}?, + attribute alt {text}? + +msline = element msline {msline.attributes,empty} +msline.attributes = + MathMLPGlobalAttributes, + attribute position {integer}?, + attribute length {unsigned-integer}?, + attribute leftoverhang {length-percentage}?, + attribute rightoverhang {length-percentage}?, + attribute mslinethickness {length-percentage | "thin" | "medium" | "thick"}? + +MalignExpression = maligngroup|malignmark + +malignmark = element malignmark {malignmark.attributes, empty} +malignmark.attributes = MathMLPGlobalAttributes + + +maligngroup = element maligngroup {maligngroup.attributes, empty} +maligngroup.attributes = MathMLPGlobalAttributes + + +PresentationExpression = TokenExpression| + mrow|mfrac|msqrt|mroot|mstyle|merror|mpadded|mphantom| + mfenced|menclose|msub|msup|msubsup|munder|mover|munderover| + mmultiscripts|mtable|mstack|mlongdiv|maction + + +mrow.attributes &= + MathMLlink.attributes + + +mfrac.attributes &= + attribute numalign {"left" | "center" | "right"}?, + attribute denomalign {"left" | "center" | "right"}?, + attribute bevelled {mathml-boolean}? + + + +mstyle.attributes &= + mstyle.specificattributes, + mstyle.generalattributes + +mstyle.specificattributes = + attribute scriptsizemultiplier {number}?, + attribute scriptminsize {length-percentage}?, + attribute infixlinebreakstyle {"before" | "after" | "duplicate"}?, + attribute decimalpoint {character}? + +# METANORMA MODIFICATION (basicdoc-models#39): `dir`, `mathsize` and +# `mathvariant` are removed from mstyle.generalattributes below — they are +# already carried by MathMLPGlobalAttributes (mathml4-core.rnc), and since +# math.attributes and mstyle.attributes combine both sets, RELAX NG's +# duplicate-attribute restriction rejects the composed grammar (jing: +# 'duplicate attribute "dir"'). The attributes remain available on every +# element via MathMLPGlobalAttributes. +mstyle.generalattributes = + attribute accent {mathml-boolean}?, + attribute accentunder {mathml-boolean}?, + attribute align {"left" | "right" | "center"}?, + attribute bevelled {mathml-boolean}?, + attribute charalign {"left" | "center" | "right"}?, + attribute charspacing {length-percentage | "loose" | "medium" | "tight"}?, + attribute close {text}?, + attribute columnalign {list {columnalignstyle+} }?, + attribute columnlines {list {linestyle +}}?, + attribute columnspacing {list {(length-percentage) +}}?, + attribute columnspan {positive-integer}?, + attribute columnwidth {list {("auto" | length-percentage | "fit") +}}?, + attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, + attribute denomalign {"left" | "center" | "right"}?, + attribute depth {length-percentage}?, + attribute equalcolumns {mathml-boolean}?, + attribute equalrows {mathml-boolean}?, + attribute form {"prefix" | "infix" | "postfix"}?, + attribute frame {linestyle}?, + attribute framespacing {list {length-percentage, length-percentage}}?, + attribute height {length-percentage}?, + attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?, + attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?, + attribute indentshift {length-percentage}?, + attribute indentshiftfirst {length-percentage | "indentshift"}?, + attribute indentshiftlast {length-percentage | "indentshift"}?, + attribute indenttarget {idref}?, + attribute largeop {mathml-boolean}?, + attribute leftoverhang {length-percentage}?, + attribute length {unsigned-integer}?, + attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?, + attribute linebreakmultchar {text}?, + attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?, + attribute lineleading {length-percentage}?, + attribute linethickness {length-percentage | "thin" | "medium" | "thick"}?, + attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, + attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}?, + attribute lquote {text}?, + attribute lspace {length-percentage}?, + attribute minlabelspacing {length-percentage}?, + attribute minsize {length-percentage}?, + attribute movablelimits {mathml-boolean}?, + attribute mslinethickness {length-percentage | "thin" | "medium" | "thick"}?, + attribute notation {text}?, + attribute numalign {"left" | "center" | "right"}?, + attribute open {text}?, + attribute position {integer}?, + attribute rightoverhang {length-percentage}?, + attribute rowalign {list {verticalalign+} }?, + attribute rowlines {list {linestyle +}}?, + attribute rowspacing {list {(length-percentage) +}}?, + attribute rowspan {positive-integer}?, + attribute rquote {text}?, + attribute rspace {length-percentage}?, + attribute selection {positive-integer}?, + attribute separators {text}?, + attribute shift {integer}?, + attribute side {"left" | "right" | "leftoverlap" | "rightoverlap"}?, + attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?, + attribute stretchy {mathml-boolean}?, + attribute subscriptshift {length-percentage}?, + attribute superscriptshift {length-percentage}?, + attribute symmetric {mathml-boolean}?, + attribute valign {length-percentage}?, + attribute width {length-percentage}? + + +math.attributes &= mstyle.specificattributes +math.attributes &= mstyle.generalattributes +math.attributes &= attribute overflow {"linebreak" | "scroll" | "elide" | "truncate" | "scale"}? + +mfenced = element mfenced {mfenced.attributes, ImpliedMrow} +mfenced.attributes = + MathMLPGlobalAttributes, + attribute open {text}?, + attribute close {text}?, + attribute separators {text}? + + +menclose = element menclose {menclose.attributes, ImpliedMrow} +menclose.attributes = + MathMLPGlobalAttributes, + attribute notation {text}? + + +munder.attributes &= + attribute align {"left" | "right" | "center"}? + +mover.attributes &= + attribute align {"left" | "right" | "center"}? + +munderover.attributes &= + attribute align {"left" | "right" | "center"}? + +msub.attributes &= + attribute subscriptshift {length-percentage}? + +msup.attributes &= + attribute superscriptshift {length-percentage}? + +msubsup.attributes &= + attribute subscriptshift {length-percentage}?, + attribute superscriptshift {length-percentage}? + + +mtable.attributes &= + attribute align {xsd:string { + pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?, + attribute rowalign {list {verticalalign+} }?, + attribute columnalign {list {columnalignstyle+} }?, + attribute columnwidth {list {("auto" | length-percentage | "fit") +}}?, + attribute width {"auto" | length-percentage}?, + attribute rowspacing {list {(length-percentage) +}}?, + attribute columnspacing {list {(length-percentage) +}}?, + attribute rowlines {list {linestyle +}}?, + attribute columnlines {list {linestyle +}}?, + attribute frame {linestyle}?, + attribute framespacing {list {length-percentage, length-percentage}}?, + attribute equalrows {mathml-boolean}?, + attribute equalcolumns {mathml-boolean}? + # METANORMA MODIFICATION (basicdoc-models#39): `attribute displaystyle` + # removed from the mtable augmentation — MathMLPGlobalAttributes + # (mathml4-core.rnc) already carries displaystyle on every element, and + # RELAX NG's duplicate-attribute restriction rejects the re-declaration + # (jing: 'duplicate attribute "displaystyle"'). + + +mtr.attributes &= + attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?, + attribute columnalign {list {columnalignstyle+} }? + + +mtd.attributes &= + attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?, + attribute columnalign {columnalignstyle}? + + +mstack = element mstack {mstack.attributes, MstackExpression*} +mstack.attributes = + MathMLPGlobalAttributes, + attribute align {xsd:string { + pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?, + attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?, + attribute charalign {"left" | "center" | "right"}?, + attribute charspacing {length-percentage | "loose" | "medium" | "tight"}? + + +mlongdiv = element mlongdiv {mlongdiv.attributes, MstackExpression,MstackExpression,MstackExpression+} +mlongdiv.attributes = + msgroup.attributes, + attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}? + + +msgroup = element msgroup {msgroup.attributes, MstackExpression*} +msgroup.attributes = + MathMLPGlobalAttributes, + attribute position {integer}?, + attribute shift {integer}? + + +msrow = element msrow {msrow.attributes, MsrowExpression*} +msrow.attributes = + MathMLPGlobalAttributes, + attribute position {integer}? + + +mscarries = element mscarries {mscarries.attributes, (MsrowExpression|mscarry)*} +mscarries.attributes = + MathMLPGlobalAttributes, + attribute position {integer}?, + attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, + attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?, + attribute scriptsizemultiplier {number}? + + +mscarry = element mscarry {mscarry.attributes, MsrowExpression*} +mscarry.attributes = + MathMLPGlobalAttributes, + attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?, + attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}? + + diff --git a/grammars/mathml/mathml4-strict-content.rnc b/grammars/mathml/mathml4-strict-content.rnc new file mode 100644 index 0000000..fd563ba --- /dev/null +++ b/grammars/mathml/mathml4-strict-content.rnc @@ -0,0 +1,105 @@ +# MathML 4 (Strict Content) +# ######################### + +# Copyright 1998-2026 W3C (MIT, ERCIM, Keio, Beihang) +# +# Use and distribution of this code are permitted under the terms +# W3C Software Notice and License +# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + + +default namespace m = "http://www.w3.org/1998/Math/MathML" + +start |= math.strict + +CommonAtt = + attribute id {xsd:ID}?, + attribute xref {text}? + +math.strict = element math {math.attributes,ContExp*} + +# METANORMA MODIFICATION (basicdoc-models#39): upstream combines CommonAtt +# (id, xref) into math.attributes here; in the full-MathML composition the +# math element already carries `id` via MathMLPGlobalAttributes +# (mathml4-core.rnc) and `xref` via the presentation augmentation +# (mathml4-presentation.rnc), so RELAX NG's duplicate-attribute restriction +# rejects the composed grammar (jing: 'duplicate attribute "id"'). +# Upstream text was: +# math.attributes &= CommonAtt + +ContExp = semantics-contexp | cn | ci | csymbol | apply | bind | share | cerror | cbytes | cs + +cn = element cn {cn.attributes,cn.content} +cn.content = text +cn.attributes = CommonAtt, attribute type {"integer" | "real" | "double" | "hexdouble"} + +semantics-ci = element semantics {CommonAtt,(ci|semantics-ci), + (annotation|annotation-xml)*} + +semantics-contexp = element semantics {CommonAtt,MathExpression, + (annotation|annotation-xml)*} + +annotation |= element annotation {CommonAtt,text} + +# METANORMA MODIFICATION (basicdoc-models#39): upstream re-opens +# `anyElement` and `annotation-xml` here with combine=choice (|=). RELAX NG +# permits only one combine method per name, which blocks the metanorma +# wrapper's `&= notAllowed` bans (metanorma-mathml.rnc) of these foreign +# markup escape hatches. The re-opens are dropped: the base definitions in +# mathml4-core.rnc remain, and the wrapper forbids them outright anyway. +# Upstream text was: +# anyElement |= element (* - m:*) {(attribute * {text}|text| anyElement)*} +# annotation-xml |= element annotation-xml {annotation-xml.attributes, +# (MathExpression*|anyElement*)} + +annotation-xml.attributes &= CommonAtt, cd?, encoding? + +# METANORMA MODIFICATION (basicdoc-models#39): upstream combines a second +# `attribute encoding` into the `encoding` define (already defined in +# mathml4-core.rnc); the interleave yields the same attribute twice wherever +# the define is used, which RELAX NG forbids (jing: 'duplicate attribute +# "encoding"'). +# Upstream text was: +# encoding &= attribute encoding {xsd:string} + + + + +ci = element ci {ci.attributes, ci.content} +ci.attributes = CommonAtt, ci.type? +ci.type = attribute type {"integer" | "rational" | "real" | "complex" | "complex-polar" | "complex-cartesian" | "constant" | "function" | "vector" | "list" | "set" | "matrix"} +ci.content = text + + +csymbol = element csymbol {csymbol.attributes,csymbol.content} + +SymbolName = xsd:NCName +csymbol.attributes = CommonAtt, cd +csymbol.content = SymbolName +cd = attribute cd {xsd:NCName} +name = attribute name {xsd:NCName} +src = attribute src {xsd:anyURI}? + +BvarQ = bvar* +bvar = element bvar {CommonAtt, (ci | semantics-ci)} + +apply = element apply {CommonAtt,apply.content} +apply.content = ContExp+ + + +bind = element bind {CommonAtt,bind.content} +bind.content = ContExp,bvar*,ContExp + +share = element share {CommonAtt, src, empty} + +cerror = element cerror {cerror.attributes, csymbol, ContExp*} +cerror.attributes = CommonAtt + +cbytes = element cbytes {cbytes.attributes, base64} +cbytes.attributes = CommonAtt +base64 = xsd:base64Binary + +cs = element cs {cs.attributes, text} +cs.attributes = CommonAtt + +MathExpression |= ContExp diff --git a/grammars/mathml/mathml4.rnc b/grammars/mathml/mathml4.rnc new file mode 100644 index 0000000..9db945e --- /dev/null +++ b/grammars/mathml/mathml4.rnc @@ -0,0 +1,29 @@ +# MathML 4 (full) +# ############## + +# Copyright 1998-2026 W3C (MIT, ERCIM, Keio) +# +# Use and distribution of this code are permitted under the terms +# W3C Software Notice and License +# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +default namespace m = "http://www.w3.org/1998/Math/MathML" + +# Presentation MathML +# METANORMA MODIFICATION (basicdoc-models#39): upstream overrides +# `anyElement` inside this include, but `anyElement` is defined in +# mathml4-core.rnc, i.e. an include nested below mathml4-presentation.rnc; +# libxml2's RELAX NG cannot override a define from a nested include (the +# same constraint documented in metanorma-mathml.rnc). The override is +# redundant for metanorma, whose wrapper bans anyElement outright. +# Upstream text was: +# include "mathml4-presentation.rnc" { +# anyElement = element (* - m:*) {(attribute * {text}|text| anyElement)*} +# } +include "mathml4-presentation.rnc" + + +# Content MathML +include "mathml4-content.rnc" + + diff --git a/grammars/mathml/metanorma-mathml.rnc b/grammars/mathml/metanorma-mathml.rnc index 08e7e6a..b74b326 100644 --- a/grammars/mathml/metanorma-mathml.rnc +++ b/grammars/mathml/metanorma-mathml.rnc @@ -1,31 +1,44 @@ -# Metanorma wrapper around the vendored W3C MathML 3.0 RelaxNG grammar. -# Includes the unmodified W3C grammar (start = math) and augments it with +# Metanorma wrapper around the vendored W3C MathML 4 RelaxNG grammar +# (vendored with marked modifications -- see README.adoc). +# Includes the W3C grammar (start = math) and augments it with # metanorma's owned extension attributes. Referenced from basicdoc.rnc via: # mathml = external "mathml/metanorma-mathml.rnc" # Authoritative param list for data-metanorma-numberformat lives in plurimath # (Formatter::Standard::DEFAULT_OPTIONS); see metanorma/basicdoc-models#35. +# MathML 3 -> 4 migration: metanorma/basicdoc-models#39 / +# metanorma/metanorma#585. -include "mathml3.rnc" +include "mathml4.rnc" # metanorma number-formatting hint on ; opaque comma-separated option # string parsed at presentation time (no-namespace data- attribute, which -# the W3C CommonAtt/NonMathMLAtt does not otherwise permit). +# the W3C MathMLPGlobalAttributes/NonMathMLAtt does not otherwise permit). mn.attributes &= attribute data-metanorma-numberformat { text }? # Foreign annotation-xml considered harmful: the metanorma lutaml-model # serialiser emits no foreign markup, so the W3C annotation-xml escape hatch # (and its anyElement wildcard) is forbidden in the MathML we process. This # also removes the untyped `id` attribute the wildcard permits, which clashes -# with xsd:ID under RELAX NG ID-type consistency (the callout-annotation error). -# metanorma only emits presentation MathML; pre-empting the escape hatch before -# semantic MathML is ever wired. Text-only is retained. +# with xsd:ID under RELAX NG ID-type consistency (the callout-annotation +# error). metanorma only emits presentation MathML; pre-empting the escape +# hatch before semantic MathML is ever wired. Text-only is +# retained. # # Expressed via `combine` (interleave with notAllowed) rather than an # include-override: annotation-xml/anyElement are defined in the transitively -# included mathml3-common, and libxml2's RelaxNG (used by Nokogiri for fragment +# included mathml4-core, and libxml2's RelaxNG (used by Nokogiri for fragment # / passthrough validation) cannot override a define from a nested include -- # it demands the combine attribute and otherwise fails to compile the whole # grammar (every passthrough then wrongly reports "Invalid passthrough # content"). jing accepts both forms; combine satisfies both. basicdoc-models#35 annotation-xml &= notAllowed anyElement &= notAllowed + +# NOTE on MathML 4's token content model: upstream `textorHTML` +# (mathml4-core.rnc) admits embedded XHTML/SVG inside token elements +# (mi/mn/mo/mtext/ms). That loosening is removed as a marked modification in +# the vendored core file itself: libxml2's RELAX NG rejects the compiled svg +# branch outright (breaking all passthrough validation), and metanorma's +# serialiser never emits embedded HTML/SVG in math tokens. See the +# METANORMA MODIFICATION comment in mathml4-core.rnc and +# metanorma/basicdoc-models#39.