---
-
  name: whitespace-omission
  tag: "!*"
  match: "not(self::m:math) and not($MatchingWhitespace) and (@data-previous-space-width >= 0.7 or @data-following-space-width >= 0.7)"
  replace:
   - with:
      variables: [MatchingWhitespace: "true()"]
      replace:
      - test:
        - if: "@data-previous-space-width > 1.1"
          then: [t: "⠿"]
          # non-breaking space width; also avoid spaces added after commas in scripts (78_1)
        - else_if: "@data-previous-space-width >= 0.7 and
                    ($NewScriptContext='' or not(preceding-sibling::*[1][self::m:mo and .=',']))"
          then: [t: "W"]
      - x: "."
      - test:
        - if: "@data-following-space-width > 1.1"
          then: [t: "⠿"]
          # non-breaking space width; also avoid spaces added after commas in scripts (78_1)
        - else_if: "@data-following-space-width >= 0.7 and
                    ($NewScriptContext='' or not(self::m:mo and .=','))"
          then: [t: "W"]

-
   name: default
   tag: msqrt
   match: "."
   replace: 
   - T: "⠩"
   - x: "*"
   - T: "⠱"

-
   name: default
   tag: mroot
   match: "."
   replace: 
   - T: "⠩⠔"
   - test:
      if:   # FIX: need to add arbitrary shapes here (see also msub/msup)
      - "*[2][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
              # next test is to make sure there is just one symbol
      - "     ((self::m:mi or self::m:mo) and string-length(text())=1) or"
      - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
      - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
      - "     IsInDefinition(., 'Braille', 'Arrows')"
      - "    ]"
      then:
      - x: "*[2]"
      else:
      - T: "⠣"
      - x: "*[2]"
      - T: "⠱"
   - T: "#"    # signal end of script/numeric mode
   - x: "*[1]"
   - T: "⠱"
        
               
# Fraction rules
   # The fraction part of a mixed number is always simple
   # They also differ because a two character sequence is needed to bracket the fraction
   # The invisible plus should produce an empty string

-
   name: common-fraction-mixed-number
   tag: mfrac
   match:
      - "preceding-sibling::*[1][self::m:mo][.='\u2064'] and" # preceding element is invisible plus
      - "*[1][self::m:mn][not(contains(., '.'))]   and" 
      - "*[2][self::m:mn][not(contains(., '.'))]"
   replace: 
   - T: "#"    # signal end of previous numeric mode
   - x: "*[1]"
   - test:
      if: "$Vietnam_UseDropNumbers"
      then:
      - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Vietnam')"   # drop numbers for the denominator
      else:
      - T: "N⠌"
      - x: "*[2]"

-
   name: simple-number
   tag: mfrac
   match: "*[1][self::m:mn] and *[2][self::m:mn]"
   replace: 
   - T: "#"    # signal end of any previous numeric mode (probably not needed, but...)
   - x: "*[1]"
   - test:
      if: "$Vietnam_UseDropNumbers"
      then:
      - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Vietnam')"   # drop numbers for the denominator
      else:
      - T: "N⠌"
      - x: "*[2]"

-
   name: default
   tag: mfrac
   match: "."
   replace: 
   - T: "⠆"
   - x: "*[1]"
   - T: "⠌"
   - x: "*[2]"
   - T: "⠰"

-
   #GTM 14.3.3 (not sure what else vertical juxtaposition applies to)
   name: binomial-frac
   tag: mrow
   match: "IsBracketed(., '(', ')') and *[2][self::m:mfrac][@linethickness=0]"
   replace: 
   - x: "*[1]"
   - x: "*[2]/*[1]"
   - t: "⠰⠻"
   - x: "*[2]/*[2]"
   - x: "*[3]"

- name: binomial-table
  tag: mrow
  match: "IsBracketed(., '(', ')') and *[2][self::m:mtable][count(*)=2 and count(*[1])=1] and contains(@intent, 'binomial(')"
  replace:
     - x: "*[1]"
     - x: "*[2]/*[1]/*[1]/*[1]"
     - t: "⠰⠻"
     - x: "*[2]/*[2]/*[1]/*[1]"
     - x: "*[3]"

#
# Matrix/Determinant rules
# matrix and determinant are the same other than "matrix"/"determinant" based on the bracketing chars
# we don't do spatial layout, instead the beginning/ending of each row uses the enlarged bracketing chars
-
   name: default-matrix
   tag: mrow
   variables:
      - RowStart: "*[1]"
      - RowEnd: "*[3]"
   match:
      - "*[2][self::m:mtable] and"
      - (IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))
   replace: [x: "*[2]"]
-
   name: default-cases
   tag: mrow
   variables:
      - RowStart: "*[1]"
      - RowEnd: "''"
   match: "*[2][self::m:mtable] and count(*)=2 and *[1][.='{' or .='[' or .='(']"
   replace: [x: "*[2]"]
-
   name: default-mtable
   tag: mtable
   match: "."
   replace: [x: "*"]
-
  name: default
  tag: [mtr, mlabeledtr]
  match: "."
  replace:
   - test:
      if: "preceding-sibling::*"
      then: [t: "⣍"]
   - t: ""
   - x: $RowStart
   - test:
      if: .[self::m:mlabeledtr]
      then:
         - t: "⠗⠕⠺W⠇⠁⠃⠑⠇⠸⠒"  # "row label:"
         - x: "*[1]/*"           # contents of row label
   - test:
      if: .[self::m:mlabeledtr]
      then: [x: "*[position()>1]"]
      else: [x: "*"]
   - x: $RowEnd
-
  name: default
  tag: mtd
  match: "."
  replace:
  - test:
      if: "*"
      then:
      - test: 
         if: "preceding-sibling::*"
         then: [t: "W"]
      - x: "*"
      # else nothing to braille

-
  name: no-content
  tag: math
  match: "not(*)"      # empty
  replace: [t: "W"]    # not sure that is right, but this shouldn't happen

-
  name: default
  tag: math
  match: "."
  variables:
  - RowStart: "''"           # empty string -- it needs to be set
  - RowEnd: "''"             # empty string -- it needs to be set
  - NewScriptContext: "''"    # empty string -- it needs to be set
  - MatchingWhitespace: "false()"
  replace: [x: "*"]

-
  name: empty-mrow
  tag: mrow
  match: "not(*)"
  replace: [t: "W"] # not sure what is correct -- if in a fraction, probably something is better than nothing

-
  name: default
  tag: mrow
  match: "."
  replace: [x: "*"]

- name: chemical-formula-operator-bond
  tag: mo
  match: "@data-chemical-bond"
  replace:
  # FIX: this might be better/more efficient if in unicode.yaml
  - bookmark: "@id"
  - test:
    - if: ".='-' or .=':'"
      then: [t: "⠤"]
    - else_if: ".='=' or .='∷'"
      then: [t: "⠭"]
    - else_if: ".='≡'"
      then: [t: "⠿"]
    - else_if: ".='≣'"
      then: [t: "⠸⠠⠤"]      # see #237 -- not defined, so use UEB
      else: [x: "text()"]    # shouldn't happen

-
   # add space after these ops when they are prefix operators
   # note: other shapes are <mi>s and canonicalization turns them into function calls (which will include spaces after them)
   name: prefix-geometry-ops
   tag: mo
   match:
      - "parent::*[count(*) = 2 and name()='mrow' and not(preceding-sibling::*)] and"
      - "IsInDefinition(., 'Braille', 'GeometryPrefixOperators')"
   replace:
      - x: "text()"
      - t: ""

-
   name: default
   tag: mo
     # add spaces around comparison operators unless they are in a script position,
   variables: [MaybeAddSpaces: "parent::*[self::m:mrow] and $NewScriptContext='' and IsInDefinition(., 'Braille', 'NemethComparisonOperators')"]
   match: "."
   replace:
      - test:
         if: "$MaybeAddSpaces"
         then:
            - test:
               if: "preceding-sibling::* and 
                    not(IsInDefinition(preceding-sibling::*[1], 'Braille', 'NemethPunctAndOpenBeforeSymbols'))" #Rule 151
               then: [t: ""]
      - x: "text()"
      - test:
         if: "$MaybeAddSpaces and following-sibling::* and 
              not(IsInDefinition(following-sibling::*[1], 'Braille', 'NemethPunctAndOpenAfterSymbols'))" #Rule 151"
         then: [t: ""]

-
  name: default
  tag: mn
  match: "."
  replace:
  - x: "BrailleChars(., 'Vietnam')"

- 
  name: sin
  tag: mi
  match: ".='sin'"
  replace:
  - t: "⠻⠎"
   
- 
  name: cos
  tag: mi
  match: ".='cos'"
  replace:
  - t: "⠻⠉"
   
- 
  name: tan
  tag: mi
  match: ".='tan'"
  replace:
  - t: "⠻⠞"
   
- 
  name: cot
  tag: mi
  match: ".='cot'"
  replace:
  - t: "⠻⠉⠞"
   
- 
  name: arcsin
  tag: mi
  match: ".='arcsin'"
  replace:
  - t: "⠁⠗⠉⠻⠎"
   
- 
  name: arccos
  tag: mi
  match: ".='arccos'"
  replace:
  - t: "⠁⠗⠉⠻⠉"
   
- 
  name: arctan
  tag: mi
  match: ".='arctan'"
  replace:
  - t: "⠁⠗⠉⠻⠞"
   
- 
  name: arccot
  tag: mi
  match: ".='arccot'"
  replace:
  - t: "⠁⠗⠉⠻⠉⠞"

-
  # FIX: need to deal with all caps
  name: default
  tag: [mi, mtext]
  match: "."
  replace:
  - test:
      if:
      - "IsInDefinition(., 'Braille', 'Units') or"
      - "(string-length(.)=1 and @mathvariant='normal' and"
          # avoid chemical elements and also states (e.g., "(g)")
      - " not(@data-chem-element) and parent::*[1][not(@data-chem-equation>='1')]"
      - ")"
      then: [t: "W"]
  - x: "BrailleChars(., 'Vietnam')"
      

-
  name: default
  tag: mstyle
  match: "."
  replace:
  - test:
      if: "*"
      then: [x: "*"]
      # else do nothing -- no content

-
  # this captures the output for the mhchem's "<=>", "<<=>", and "<=>>" output (there are no Unicode arrows for them)
  # this isn't a perfect match, but should be good enough and allows merging all three (see github.com/NSoiffer/MathCAT/issues/60)
  name: chemistry-mhchem-equilibrium-arrow
  tag: mover
  match:
  -    "*[1][substring(., 1, 1)='↽'] and"
  -    "*[2][substring(., string-length(), 1)='⇀']"
  replace:
  - test:
      if: "*[1][self::m:mrow]"
      then_test:
          if: "*[2][self::m:mrow]"
          then: [x: "'🣑'"]    # \u1f8d1 this is currently unassigned and may get used by UTC at some point (<=>)
          else: [x: "'🣓'"]    # \u1f8d3 this is currently unassigned and may get used by UTC at some point (<<=>)
      else: [x: "'🣒'"]        # \u1f8d2 this is currently unassigned and may get used by UTC at some point (<==>>)

-
  name: angle   # angles need a shape indicator -- not sure this is the best test (three letters in base, have invisible separators)
  tag: mover
  match: "*[2][.='^'] and *[1][
            self::m:mrow and count(*)=5 and
            *[1][self::m:mi] and *[2][.='\u2063'] and *[3][self::m:mi] and *[4][.='\u2063'] and *[5][self::m:mi]
          ]"
  replace:
  - t: "⠫⠛"     # shape indicator, g
  - x: "*[1]"

-
  name: overparen
  tag: mover
  match: "*[2][.='⏜']"
  replace:
  - t: "⠫⠠⠗"     # shape indicator, overparen
  - x: "*[1]"

-
   name: single-char-exceptions    # GTM 12
   tag: [mover, munder]
   match: "*[2][string-length(.) = 1 and ( translate(., '_¯→.˙~^','')='' or (self::m:mover and .='⌒') )]"
   replace: 
   - test:
      # omit grouping indicators in the following cases
      if:   # FIX: need to add arbitrary shapes here (also for mroot)
      - "(*[1][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
              # next test is to make sure there is just one symbol
      - "     ((self::m:mi or self::m:mo) and string-length(text())=1) or"
      - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
      - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
      - "     IsInDefinition(., 'Braille', 'Arrows')"
      - "    ]) and"
      - "not(*[1][self::m:mn] and preceding-sibling::*[1][.='\u2062'][preceding-sibling::*[1][self::m:mn]])"  # need to make clear this 'mn' is base
      then: [x: "*[1]"]
      else:
      - t: "⠣"
      - x: "*[1]"
      - t: "⠜"
   - test:
      if: "*[2][translate(., '_¯→^', '') = '']"
      then: [t: ""]
   - test:
      if: "self::m:munder"
      then: [t: "⠠"]
   - test:
      - if: "*[2][.='_' or .='¯']"
        then: [T: "⠨⠱"]
      - else_if: "*[2][.='→']"
        then: [T: "⠨⠔⠳⠕"]
      - else_if: "*[2][.='.' or .='˙']"
        then: [t: "⠘⠲"]
      - else_if: "*[2][.='~']"
        then: [t: "⠸⠱"]
      - else_if: "*[2][.='^']"
        then: [t: "⠐⠱ "]
        else: [t: "⠨⠸⠱"]    # arc/⌒

-
   name: single-char-exceptions    # RUEB 3.11 -- ° and various prime/minute/seconds aren't treated as if superscripts
   tag: msup
   match: "*[2][translate(., \"'*`ª°²³´¹º‘’“”‟′″‴‵‶‷⁗\",'')='']"
   replace: [x: "*"]

-
   name: default
   tag: [msub, msup, munder, mover]
   match: "."
   replace: 
   - test:
      # omit grouping indicators in the following cases
      if:
      - "not((self::m:mover or self::m:munder) and "
      - "    *[1][self::m:mn] and preceding-sibling::*[1][.='\u2062'][preceding-sibling::*[1][self::m:mn]]"  # need to make clear this 'mn' is base
      - "   )"
      then: [x: "*[1]"]
      else:
      - t: "⠣"
      - x: "*[1]"
      - t: "⠜"
   - with:   # this could be tighter and be just around the *[2] part, but this is consistent with msubsup below
      variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
      replace:
      - test:
         - if: "self::m:msup"
           then: [T: "⠔"]
         - else_if: "self::m:msub"
           then: [T: "⠢"]
         - else_if: "self::m:munder"
           then: [T: "⠢"]
           else: [T: "⠔"]  # mover
      - test:
         # omit grouping indicators in the following cases
         if:   # FIX: need to add arbitrary shapes here (also for mroot) also multi-char leaf translations except mi
         - "*[2][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
              # next test is to make sure there is just one symbol
              # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
         - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
         - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
         - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
         - "     IsInDefinition(., 'Braille', 'Arrows')"
         - "    ]"
         then: [x: "*[2]"]
         else:
         - t: "⠣"
         - x: "*[2]"
         - t: "⠱"
   - t: "#"   # signal end script/numeric mode

- name: log-base-power
  tag: msubsup
  match: "*[1][.='log']"
  replace:
  - x: "*[1]"   # log
  - T: "⠔"
  - x: "*[3]"   # superscript
  - T: "⠢"
  - x: "*[2]"   # supscript

-
   name: msubsup_default_mmultiscripts_equiv
   tag: [msubsup, munderover] # mmultiscripts with only sub/sup postscript
   match: "count(*)=3"    # catches mmultiscripts equiv
   replace: 
   - test:
      # omit grouping indicators in the following cases
      if:   # FIX: need to add arbitrary shapes here (also for mroot)
      - "*[1][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                     # next test is to make sure there is just one symbol
                     # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
      - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
      - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
      - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
      - "     IsInDefinition(., 'Braille', 'Arrows')"
      - "    ]"
      then: [x: "*[1]"]
      else:
      - t: "⠣"
      - x: "*[1]"
      - t: "⠜"
   - with: 
      variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
      replace:
      - test:
         - if: "self::m:munderover"
           then: [t: "⠢"]    
           else: [t: "⠢"]
      - test:
         # omit grouping indicators in the following cases
         if:   # FIX: need to add arbitrary shapes here (also for mroot) also multi-char leaf translations except mi
         - "*[2][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
              # next test is to make sure there is just one symbol
              # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
         - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
         - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
         - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
         - "     IsInDefinition(., 'Braille', 'Arrows')"
         - "    ]"
         then: [x: "*[2]"]
         else:
         - t: "⠣"
         - x: "*[2]"
         - t: "⠜"
      - test:
         - if: "self::m:munderover"
           then: [T: "⠔"]     
           else: [T: "⠔"]
      - test:
         # omit grouping indicators in the following cases
         if:   # FIX: need to add arbitrary shapes here (also for mroot) also multi-char leaf translations except mi
         - "*[3][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
              # next test is to make sure there is just one symbol
              # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
         - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
         - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
         - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
         - "     IsInDefinition(., 'Braille', 'Arrows')"
         - "    ]"
         then: [x: "*[3]"]
         else:
         - t: "⠣"
         - x: "*[3]"
         - t: "⠜"
   - t: "#"   # signal end script/numeric mode

-
   name: default
   tag: mmultiscripts
   match: "."
   variables:
   # computing the number of postscripts is messy because of <mprescripts> being optionally present -- we use "mod" to get the count right
   - Prescripts: "m:mprescripts/following-sibling::*"
   - NumChildren: "count(*)"       # need to stash this since the count is wrong inside '*[...]' below
   - Postscripts: "*[position()>1 and position() < (last() + ($NumChildren mod 2) -count($Prescripts))]"
   replace:
   - x: "*[1]"
   - test:
      if: "$Prescripts"
      then:
      - test:
         if: "not($Prescripts[1][self::m:none])"
         then:
         - with:
            variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
            replace:
            - t: "⠢⠮"
            - test:
               # omit grouping indicators in the following cases
               if:   # FIX: need to add arbitrary shapes here (also for mroot)
               - "$Prescripts[1][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                  # next test is to make sure there is just one symbol
                  # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
               - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
               - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
               - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
               - "     IsInDefinition(., 'Braille', 'Arrows')"
               - "    ]"
               then: [x: "$Prescripts[1]"]
               else:
               - t: "⠣"
               - x: "$Prescripts[1]"
               - t: "⠜"
      - test:
         if: "not($Prescripts[2][self::m:none])"
         then:
         - with:
            variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
            replace:
            - t: "⠔⠞"
            - test:
               # omit grouping indicators in the following cases
               if:   # FIX: need to add arbitrary shapes here (also for mroot)
               - "$Prescripts[2][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                  # next test is to make sure there is just one symbol
                  # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
               - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
               - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
               - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
               - "     IsInDefinition(., 'Braille', 'Arrows')"
               - "    ]"
               then: [x: "$Prescripts[2]"]
               else:
               - t: "⠣"
               - x: "$Prescripts[2]"
               - t: "⠜"
      - test:
         if: "count($Prescripts)>2"
         then:
         - test:
            if: "not($Prescripts[3][self::m:none])"
            then:
            - with:
               variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
               replace:
               - t: "⠢⠮"
               - test:
                  # omit grouping indicators in the following cases
                  if:   # FIX: need to add arbitrary shapes here (also for mroot)
                  - "$Prescripts[3][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                     # next test is to make sure there is just one symbol
                     # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                  - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                  - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                  - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                  - "     IsInDefinition(., 'Braille', 'Arrows')"
                  - "    ]"
                  then: [x: "$Prescripts[3]"]
                  else:
                  - t: "⠣"
                  - x: "$Prescripts[3]"
                  - t: "⠜"
         - test:
            if: "not($Prescripts[4][self::m:none])"
            then:
            - with:
               variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
               replace:
               - t: "⠔⠞"
               - test:
                  # omit grouping indicators in the following cases
                  if:   # FIX: need to add arbitrary shapes here (also for mroot)
                  - "$Prescripts[4][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                     # next test is to make sure there is just one symbol
                     # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                  - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                  - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                  - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                  - "     IsInDefinition(., 'Braille', 'Arrows')"
                  - "    ]"
                  then: [x: "$Prescripts[4]"]
                  else:
                  - t: "⠣"
                  - x: "$Prescripts[4]"
                  - t: "⠜"
         - test:
            if: "count($Prescripts) > 4"   # give up and just dump them out so at least the content is there
            then: [x: "$Prescripts[position() > 4]"]

   - test:
      if: "$Postscripts"
      then:
      - test:
         if: "not($Postscripts[1][self::m:none])"
         then:
         - with:
            variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
            replace:
            - t: "⠢"
            - test:
               # omit grouping indicators in the following cases
               if:   # FIX: need to add arbitrary shapes here (also for mroot)
               - "$Postscripts[1][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                  # next test is to make sure there is just one symbol
                  # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
               - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
               - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
               - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
               - "     IsInDefinition(., 'Braille', 'Arrows')"
               - "    ]"
               then: [x: "$Postscripts[1]"]
               else:
               - t: "⠣"
               - x: "$Postscripts[1]"
               - t: "⠱"
      - test:
         if: "not($Postscripts[2][self::m:none])"
         then:
         - with:
            variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
            replace:
            - t: "⠔"
            - test:
               # omit grouping indicators in the following cases
               if:   # FIX: need to add arbitrary shapes here (also for mroot)
               - "$Postscripts[2][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                  # next test is to make sure there is just one symbol
                  # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
               - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
               - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
               - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
               - "     IsInDefinition(., 'Braille', 'Arrows')"
               - "    ]"
               then: [x: "$Postscripts[2]"]
               else:
               - t: "⠣"
               - x: "$Postscripts[2]"
               - t: "⠱"
      - test:
         if: "count($Postscripts)>2"
         then:
         - test:
            if: "not($Postscripts[3][self::m:none])"
            then:
            - with:
               variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
               replace:
               - t: "⠢"
               - test:
                  # omit grouping indicators in the following cases
                  if:   # FIX: need to add arbitrary shapes here (also for mroot)
                  - "$Postscripts[3][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                     # next test is to make sure there is just one symbol
                     # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                  - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                  - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                  - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                  - "     IsInDefinition(., 'Braille', 'Arrows')"
                  - "    ]"
                  then: [x: "$Postscripts[3]"]
                  else:
                  - t: "⠣"
                  - x: "$Postscripts[3]"
                  - t: "⠱"
         - test:
            if: "not($Postscripts[4][self::m:none])"
            then:
            - with:
               variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
               replace:
               - t: "⠔"
               - test:
                  # omit grouping indicators in the following cases
                  if:   # FIX: need to add arbitrary shapes here (also for mroot)
                  - "$Postscripts[4][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                     # next test is to make sure there is just one symbol
                     # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                  - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                  - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                  - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                  - "     IsInDefinition(., 'Braille', 'Arrows')"
                  - "    ]"
                  then: [x: "$Postscripts[4]"]
                  else:
                  - t: "⠣"
                  - x: "$Postscripts[4]"
                  - t: "⠱"
         - test:
            if: "count($Postscripts)>4"
            then:
            - test:
               if: "not($Postscripts[5][self::m:none])"
               then:
               - with:
                  variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
                  replace:
                  - t: "⠢"
                  - test:
                     # omit grouping indicators in the following cases
                     if:   # FIX: need to add arbitrary shapes here (also for mroot)
                     - "$Postscripts[5][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                        # next test is to make sure there is just one symbol
                        # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                     - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                     - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                     - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                     - "     IsInDefinition(., 'Braille', 'Arrows')"
                     - "    ]"
                     then: [x: "$Postscripts[5]"]
                     else:
                     - t: "⠣"
                     - x: "$Postscripts[5]"
                     - t: "⠱"
            - test:
               if: "not($Postscripts[6][self::m:none])"
               then:
               - with:
                  variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
                  replace:
                  - t: "⠔"
                  - test:
                     # omit grouping indicators in the following cases
                     if:   # FIX: need to add arbitrary shapes here (also for mroot)
                     - "$Postscripts[6][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                        # next test is to make sure there is just one symbol
                        # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                     - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                     - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                     - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                     - "     IsInDefinition(., 'Braille', 'Arrows')"
                     - "    ]"
                     then: [x: "$Postscripts[6]"]
                     else:
                     - t: "⠣"
                     - x: "$Postscripts[6]"
                     - t: "⠱"
            - test:
               if: "count($Postscripts)>6"
               then:
               - test:
                  if: "not($Postscripts[7][self::m:none])"
                  then:
                  - with:
                     variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
                     replace:
                     - t: "⠢"
                     - test:
                        # omit grouping indicators in the following cases
                        if:   # FIX: need to add arbitrary shapes here (also for mroot)
                        - "$Postscripts[7][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                           # next test is to make sure there is just one symbol
                           # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                        - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                        - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                        - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                        - "     IsInDefinition(., 'Braille', 'Arrows')"
                        - "    ]"
                        then: [x: "$Postscripts[7]"]
                        else:
                        - t: "⠣"
                        - x: "$Postscripts[7]"
                        - t: "⠱"
               - test:
                  if: "not($Postscripts[8][self::m:none])"
                  then:
                  - with:
                     variables: [NewScriptContext: "in"]   # value doesn't matter -- just can't be empty string
                     replace:
                     - t: "⠔"
                     - test:
                        # omit grouping indicators in the following cases
                        if:   # FIX: need to add arbitrary shapes here (also for mroot)
                        - "$Postscripts[8][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
                           # next test is to make sure there is just one symbol
                           # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
                        - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
                        - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
                        - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
                        - "     IsInDefinition(., 'Braille', 'Arrows')"
                        - "    ]"
                        then: [x: "$Postscripts[8]"]
                        else:
                        - t: "⠣"
                        - x: "$Postscripts[8]"
                        - t: "⠱"
               - test:
                  if: "count($Postscripts) > 8"   # give up and just dump them out so at least the content is there
                  then:
                  - t: "b"    # 82.b -- need to add level indicator between adjacent (not simultaneous) scripts (assumes one of sub/super is not 'none')
                  - x: "$Postscripts[position() > 8]"
   - t: "#"   # signal end script/numeric mode
                  

-
  # Note: @notation can contain more than one value
  # I don't think UEB has a good way to represent all notations, especially when in combination
  # Note:
  #   Shape indicator: ⠫
  #   Physical enclosure: ⠪  (think plus inside of a circle)
  #   Superposition indicator: ⠯  (think contour integral)
  #   Cancellation: ⠈⠱ (line through previous char -- will use for horizontal, vertical, diagonal lines)
  #   Line over/under: use GTM 12 bar rule (over ⠱, under ⠠⠱)
  #   Horizontal juxtaposition indicator: ⠿
  #   Vertical juxtaposition indicator: ⠻ (think ≗)
  #   Termination indicator: ⠱ 
  #
  # We place left and right outside of other notations
  # Boxes and circle are does as physical enclosure (shape before base)
  # Arrows are done as superposition (after base)
  # top and bottom are done as "bars" (GTM 12) (after base)

   name: default
   tag: menclose
   match: "."
   # FIX: can't find a rule that says anything about comparison operator spacing and enclosure
   variables: [AddSpaces: "parent::*[self::m:mrow] and *[1][ self::m:mo and IsInDefinition(., 'Braille', 'NemethComparisonOperators')]"]
   replace:
   - test:
      if: "contains(concat(' ', normalize-space(@notation), ' '), ' left ')"                  #avoid 'leftarrow'
      then: [t: "⠸"]
   - test:
      if: "contains(@notation,'box')"                  # box and roundedbox
      then:
      # - test:
      #       if: "$AddSpaces"
      #       then: [t: " "]
      - T: "⠫⠼⠙"                                  # square (no rectangle in UEB)
   - test:
      if: "contains(@notation,'circle')"
      then:
      # - test:
      #    if: "$AddSpaces"
      #    then: [t: " "]
      - t: "⠫⠿"                                  # circle (no oval in UEB)
# ??? What should happen with arrow?
#  If there is a box/circle with arrows only and an empty child,
#     then it acts like the arrow is the child
#  If there are only arrows for 'notation', then maybe rule 112 applies (superposition),
#     but the examples aren't similar. In that case, the arrow acts like 'box' and the child is the content... maybe  
# 
#  - test:
#      if: "contains(@notation,'leftarrow')"
#      then: [t: left arrow, pause: short]
#  - test:
#      if: "contains(concat(' ', normalize-space(@notation), ' '), ' rightarrow ')"
#      then: [t: right arrow, pause: short]
#  - test:
#      if: "contains(@notation,'northeastarrow')"
#      then: [t: northeast arrow, pause: short]
#  - test:
#      if: "contains(concat(' ', normalize-space(@notation), ' '), ' southeastarrow ')"
#      then: [t: southeast arrow, pause: short]
#  - test:
#      if: "contains(concat(' ', normalize-space(@notation), ' '), ' southwestarrow ')"
#      then: [t: southwest arrow, pause: short]
#  - test:
#      if: "contains(@notation,'northwestarrow')"
#      then: [t: northwest arrow, pause: short]
#  - test:
#      if: "contains(@notation,'updownarrow')"
#      then: [t: double ended vertical arrow, pause: short]
#  - test:
#      if: "contains(@notation,'leftrightarrow')"
#      then: [t: double ended horizontal arrow, pause: short]
#  - test:
#      if: "contains(@notation,'northeastsouthwestarrow')"
#      then: [t: double ended up diagonal arrow, pause: short]
#  - test:
#      if: "contains(@notation,'northwestsoutheastarrow')"
#      then: [t: double ended down diagonal arrow, pause: short]
#  - test:
#      if: ".[contains(@notation,'actuarial')]"
#      then: [t: actuarial symbol, pause: short]
#  - test:
#      if: ".[contains(@notation,'madrub')]"
#      then: [t: arabic factorial symbol, pause: short]
#  - test:
#      if: ".[contains(@notation,'longdiv') or not(@notation) or normalize-space(@notation) ='']"      # default
#      then: [t: long division symbol, pause: short]
#  - test:
#      if: ".[contains(@notation,'radical')]"
#      then: [t: square root, pause: short]

   - test:
      # omit grouping indicators in the following cases
      if:   # FIX: need to add arbitrary shapes here (also for mroot) also multi-char leaf translations except mi
            # next test is to make sure there is just one symbol
            # FIX: the double dot test is likely wrong, but I can't find what other exceptions there are 
      - "*[1][(self::m:mn and not(@data-roman-numeral and string-length(text())>1)) or"
      - "     ((self::m:mi or self::m:mo) and string-length(text())=1 and text()!='¨') or"
      - "     self::m:mfrac or self::m:msqrt or self::m:mroot or"
      - "     IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '{', '}') or"
      - "     IsInDefinition(., 'Braille', 'Arrows')"
      - "    ]"
      then: [x: "*[1]"]
      else:
      - t: "⠣"
      - x: "*[1]"
      - t: "⠜"

   # - test:
   #    if: "contains(@notation,'phasorangle')"  #FIX: what should this be???
   #    then: [t: "⠫⠪⠸⠫"]
   - test:
      if: "contains(@notation,'arrow')"    # all the arrows
      then:
      - test:
         - if: "contains(@notation,'rightarrow')" 
           then: [t: "⠳⠕"]                                                           
         - else_if: "contains(@notation,'leftarrow')" 
           then: [t: "⠳⠪"]                                                           
         - else_if: "contains(@notation,'uparrow')" 
           then: [t: "⠳⠬ "]                                                           
         - else_if: "contains(@notation,'downarrow')" 
           then: [t: "⠳⠩"]                                                           
         - else_if: "contains(@notation,'northeastarrow')" 
           then: [t: "⠳⠎"]                                                           
         - else_if: "contains(@notation,'southeastarrow')" 
           then: [t: "⠳⠣"]                                                           
         - else_if: "contains(@notation,'northwestarrow')" 
           then: [t: "⠳⠱"]                                                           
         - else_if: "contains(@notation,'southwestarrow')" 
           then: [t: "⠳⠜"]                                                           
         - else_if: "contains(@notation,'leftrightarrow')" 
           then: [t: "⠳⠺⠗⠕"]                                                           
         - else_if: "contains(@notation,'updownarrow')" 
           then: [t: "⠳⠺⠗⠬"]                                                           
         - else_if: "contains(@notation,'northeastsouthwestarrow')" 
           then: [t: "⠳⠺⠗⠎"]                                                           
         - else_if: "contains(@notation,'northwestsoutheastarrow')" 
           then: [t: "⠳⠺⠗⠣"]                                                           
   - test:
      if: "contains(@notation,'top')"
      then: [T: "⠨⠱"]                                                                
   - test:
      if: "contains(@notation,'bottom')"
      then: [t: "⠠⠱"]                                                                
   - test:
      if: "contains(@notation,'updiagonalstrike') or contains(@notation,'downdiagonalstrike') or 
            contains(@notation,'verticalstrike') or contains(@notation,'horizontalstrike')"
      then:
         - t: "⠈⠱"                        # cancellation
   - test:
      if:
      - "not($AddSpaces) and contains(@notation,'box') or contains(@notation,'circle') or"
      - "contains(@notation,'arrow') or contains(@notation,'phasorangle')" 
      then:
      - t: "⠻"                   # terminate shape
      # - test:
      #    if: "$AddSpaces"
      #    then: [t: " "]
   - test:
      if: "contains(concat(' ', normalize-space(@notation), ' '), ' right ')"                  #avoid 'rightarrow'
      then: [t: "⠸"]



-
   name: default
   tag: ms
   match: "."
   replace:
      - test:
         if: "string(@lquote)!=''"
         then: [x: "@lquote"]
         else: [t: "⠄⠄"]
      - x: "BrailleChars(., 'Vietnam')"
      - test:
         if: "string(@rquote)!=''"
         then: [x: "@rquote"]
         else: [t: "⠄⠄"]

-
   name: default
   tag: semantics
   match: "."
   replace: 
      - x: "*[1]"             #/ FIX: should prioritize @encoding="MathML-Presentation" and @encoding="application/mathml-presentation+xml"

-
   name: default-children
   tag: "*"
   match: "*"    # make sure there are children
   replace: 
   - x: "BrailleChars('unknown math m l element', 'Vietnam')"
   - x: "name(.)"
   - x: "*"

-
   # at this point, we know there are no children -- might be no text
   name: default-no-children
   tag: "*"
   match: "text()"
   replace: 
   - x: "BrailleChars('unknown math m l element', 'Vietnam')"
   - x: "name(.)"
   - x: "text()"

-
   name: default-no-text
   tag: "*"
   match: "."
   replace: 
    - x: "BrailleChars('empty unknown math m l element', 'Vietnam')"
    - x: "name(.)"
