--- #default rules shared among several speech rules - name: default tag: math match: "." replace: - with: variables: - ClearSpeak_Fractions: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Fractions='Auto', 'EndFrac', $ClearSpeak_Fractions)" - ClearSpeak_AbsoluteValue: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_AbsoluteValue='Auto', 'AbsEnd', $ClearSpeak_AbsoluteValue)" - ClearSpeak_Roots: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Roots='Auto', 'RootEnd', $ClearSpeak_Roots)" replace: - test: if: "$MathRate = 100" then: [{x: "*"}] else: - rate: value: "$MathRate" replace: [{x: "*"}] - name: empty-mrow tag: mrow match: "not(*)" replace: - T: ' ' # say nothing -- placeholder - name: default tag: mrow match: "." replace: - insert: nodes: "*" replace: [{pause: auto}] - name: default tag: mn match: "." replace: - bookmark: "@id" - x: "translate(., $BlockSeparators, '')" # remove digit block separators - name: default tag: [mo, mtext] match: "." replace: - bookmark: "@id" - x: "text()" - name: default tag: mi match: "." replace: - bookmark: "@id" - test: if: "string-length(.) = 1" # need unicode.tdl to kick in for single letter tokens then: [x: "text()"] else: [x: "translate(., '-_\u00A0', ' ')" ] # from intent literals - name: default tag: ms match: "." replace: - T: 'string' - pause: short - x: "text()" - name: default tag: mstyle match: "." replace: [{x: "*"}] - name: simple-sub tag: particular-value-of # invisible comma -- want "x sub 1 1" without "end sub" match: "IsNode(*[2], 'leaf') or *[2][self::m:mrow][*[2][text()='⁣']]" replace: - x: "*[1]" - test: if: "$Verbosity!='Terse' or not(*[2][self::m:mn])" # just say "x 1" for terse vs "x sub 1" then: [{T: 'indeks'}] - x: "*[2]" - name: default tag: particular-value-of match: "." replace: - x: "*[1]" - T: 'indeks' - x: "*[2]" - T: 'akhir indeks' - pause: short - name: default tag: msubsup match: "." replace: - x: "*[1]" - T: "indeks" - x: "*[2]" - T: "pangkat" - x: "*[3]" - T: "baris basis" - name: default tag: munder match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [{T: 'diubah'}] - x: "*[1]" - T: 'dengan' - x: "*[2]" - T: di bawah - name: default tag: mover match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [{T: 'diubah'}] - x: "*[1]" - T: 'dengan' - x: "*[2]" - T: 'di atas' - name: default tag: munderover match: "." replace: - test: if: "not(IsNode(*[1], 'leaf'))" then: [{T: 'diubah'}] - T: 'dengan' - x: "*[1]" - pause: medium - T: 'di bawah' - x: "*[2]" - T: 'dan di atas' - x: "*[3]" - name: default # Here we support up to 2 prescripts and up to 4 postscripts -- that should cover all reasonable cases # If there are more, we just dump them out without regard to sup/super :-( # FIX: this could use more special cases # There is (currently) no way in MathCAT to deal with n-ary arguments other than "all" ('*') or an individual entry ('*[1]'). tag: mmultiscripts match: "." variables: # computing the number of postscripts is messy because of 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" # more common case then: - with: variables: - PreSubscript: "IfThenElse($Verbosity='Verbose', 'pre subscript', 'pre sub')" - PreSuperscript: "IfThenElse($Verbosity='Verbose', 'pre superscript', 'pre super')" replace: - test: # only bother announcing if there is more than one prescript if: "count($Prescripts) > 2" then: - T: "dengan" - x: "count($Prescripts) div 2" - T: "pra-superskrip" - pause: short - test: if: "not($Prescripts[1][self::m:none])" then: - x: "$PreSubscript" - x: "$Prescripts[1]" - test: if: "not($Prescripts[1][self::m:none] or $Prescripts[2][self::m:none])" then: [{T: "dan"}] - test: if: "not($Prescripts[2][self::m:none])" then: - x: "$PreSuperscript" - x: "$Prescripts[2]" - pause: short - test: if: "count($Prescripts) > 2" # more common case then: - test: if: "not($Prescripts[3][self::m:none])" then: - x: "$PreSubscript" - x: "$Prescripts[3]" - test: if: "not($Prescripts[3][self::m:none] or $Prescripts[4][self::m:none])" then: [{T: "dan"}] - test: if: "not($Prescripts[4][self::m:none])" then: - x: "$PreSuperscript" - x: "$Prescripts[4]" - test: if: "count($Prescripts) > 4" # give up and just dump them out so at least the content is there then: - T: "dan bergantian pra-superskrip" - x: "$Prescripts[position() > 4]" - T: "akhir pra-superskrip" - test: if: "$Postscripts" then: - with: variables: - PostSubscript: "IfThenElse($Verbosity='Verbose', 'subscript', 'sub')" - PostSuperscript: "IfThenElse($Verbosity='Verbose', 'superscript', 'super')" replace: - test: # only bother announcing if there is more than one postscript if: "count($Postscripts) > 2" then: - test: if: "$Prescripts" then: [{T: "dan"}] - T: "dengan" - x: "count($Postscripts) div 2" - T: "postskrip" - pause: short - test: if: "not($Postscripts[1][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[1]" - test: if: "not($Postscripts[1][self::m:none] or $Postscripts[2][self::m:none])" then: [{T: "dan"}] - test: if: "not($Postscripts[2][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[2]" - test: if: "count($Postscripts) > 2" then: - test: if: "not($Postscripts[3][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[3]" - test: if: "not($Postscripts[3][self::m:none] or $Postscripts[4][self::m:none])" then: [{T: "dan"}] - test: if: "not($Postscripts[4][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[4]" - test: if: "count($Postscripts) > 4" then: - test: if: "not($Postscripts[5][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[5]" - test: if: "not($Postscripts[5][self::m:none] or $Postscripts[6][self::m:none])" then: [{T: "dan"}] - test: if: "not($Postscripts[6][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[6]" - test: if: "count($Postscripts) > 6" then: - test: if: "not($Postscripts[7][self::m:none])" then: - x: "$PostSubscript" - x: "$Postscripts[7]" - test: if: "not($Postscripts[7][self::m:none] or $Postscripts[8][self::m:none])" then: [{T: "dan"}] - test: if: "not($Postscripts[8][self::m:none])" then: - x: "$PostSuperscript" - x: "$Postscripts[8]" - test: if: "count($Postscripts) > 8" # give up and just dump them out so at least the content is there then: - T: "dan skrip bergantian" - x: "$Postscripts[position() > 8]" - T: "akhir skrip" - name: default tag: mtable variables: [{IsColumnSilent: false()}] match: "." replace: - T: 'tabel dengan' - x: count(*) - test: if: count(*)=1 then: {T: 'baris'} else: {T: 'baris'} - T: dan - x: "count(*[1]/*)" - test: if: "count(*[1]/*)=1" then: {T: 'kolom'} else: {T: 'kolom'} - pause: long - x: "*" - # this may get called from navigation -- in that case, there is no context to speak the row #, so don't do it # callers/context should do that. name: default tag: mtr match: "." replace: - x: "*" - name: default tag: mtd match: "." replace: - T: 'kolom' - x: "count(preceding-sibling::*)+1" - pause: medium - x: "*" # speak the entry - pause: long - # Note: @notation can contain more than one value # The ordering below is the order in which words come out when there is more than one value name: default tag: menclose match: "." replace: - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' box ')]" then: [{T: kotak}, {pause: short}] - test: if: ".[contains(@notation,'roundedbox')]" then: [{T: kotak bulat}, {pause: short}] - test: if: ".[contains(@notation,'circle')]" then: [{T: lingkaran}, {pause: short}] - test: if: ".[ contains(concat(' ', normalize-space(@notation), ' '), ' left ') or contains(concat(' ', normalize-space(@notation), ' '), ' right ') or contains(@notation,'top') or contains(@notation,'bottom') ]" then: - T: baris aktif - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' left ')]" then: [{T: kiri}, {pause: short}] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' right ')]" then: [{T: kanan}, {pause: short}] - test: if: ".[contains(@notation,'top')]" then: [{T: atas}, {pause: short}] - test: if: ".[contains(@notation,'bottom')]" then: [{T: bawah}, {pause: short}] - test: if: ".[ contains(@notation,'updiagonalstrike') or contains(@notation,'downdiagonalstrike') or contains(@notation,'verticalstrike') or contains(@notation,'horizontalstrike') ]" then: - test: if: ".[contains(@notation,'updiagonalstrike') and contains(@notation,'downdiagonalstrike')]" then: [{spell: x}, {pause: short}] # seems better to say 'x cross out' than 'up diagonal, down diagonal cross out' else: - test: if: ".[contains(@notation,'updiagonalstrike')]" then: [{T: diagonal ke atas}, {pause: short}] - test: if: ".[contains(@notation,'downdiagonalstrike')]" then: [{T: diagonal ke bawah}, {pause: short}] - test: if: ".[contains(@notation,'verticalstrike')]" then: [{T: vertikal}, {pause: short}] - test: if: ".[contains(@notation,'horizontalstrike')]" then: [{T: horizontal}, {pause: short}] - T: mencoret - pause: short - test: if: ".[contains(@notation,'uparrow')]" then: [{T: panah atas}, {pause: short}] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' downarrow ')]" then: [{T: panah bawah}, {pause: short}] - test: if: ".[contains(@notation,'leftarrow')]" then: [{T: panah kiri}, {pause: short}] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' rightarrow ')]" then: [{T: panah kanan}, {pause: short}] - test: if: ".[contains(@notation,'northeastarrow')]" then: [{T: panah timur laut}, {pause: short}] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southeastarrow ')]" then: [{T: panah tenggara}, {pause: short}] - test: if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southwestarrow ')]" then: [{T: panah barat daya}, {pause: short}] - test: if: ".[contains(@notation,'northwestarrow')]" then: [{T: panah barat laut}, {pause: short}] - test: if: ".[contains(@notation,'updownarrow')]" then: [{T: panah vertikal ujung ganda}, {pause: short}] - test: if: ".[contains(@notation,'leftrightarrow')]" then: [{T: panah horizontal ujung ganda}, {pause: short}] - test: if: ".[contains(@notation,'northeastsouthwestarrow')]" then: [{T: panah diagonal atas ujung ganda}, {pause: short}] - test: if: ".[contains(@notation,'northwestsoutheastarrow')]" then: [{T: panah diagonal bawah ujung ganda}, {pause: short}] - test: if: ".[contains(@notation,'actuarial')]" then: [{T: simbol aktuaria}, {pause: short}] - test: if: ".[contains(@notation,'madrub')]" then: [{T: simbol faktorial arab}, {pause: short}] - test: if: ".[contains(@notation,'phasorangle')]" then: [{T: sudut fasor}, {pause: short}] - test: if: ".[contains(@notation,'longdiv') or not(@notation) or normalize-space(@notation) ='']" # default then: [{T: simbol pembagian panjang}, {pause: short}] - test: if: ".[contains(@notation,'radical')]" then: [{T: akar pangkat dua}, {pause: short}] - T: melampirkan - test: if: "*[self::m:mtext and text()=' ']" then: [T: "beberapa ruang"] # (en: "some space") otherwise there is complete silence else: [x: "*"] - test: if: "$Impairment = 'Blindness' and ( $SpeechStyle != 'SimpleSpeak' or not(IsNode(*[1], 'leaf')) )" then: [{T: penutup akhir}] - pause: short - name: semantics tag: "semantics" match: "*[@encoding='MathML-Presentation']" replace: - x: "*[@encoding='MathML-Presentation']/*[1]" - name: semantics-default tag: "semantics" match: . replace: - x: "*[1]" # Here are the intent hints that need to be handled: 'prefix' | 'infix' | 'postfix' | 'function' | 'silent' - name: silent-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':silent:') and count(*)>0" replace: - x: "*" - name: prefix-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':prefix:') and count(*)>0" replace: - x: "translate(name(.), '-_', ' ')" - x: "*" - pause: short - name: postfix-intent # uncaught intent -- speak as arg1 arg2 .... tag: "*" match: "contains(@data-intent-property, ':postfix:') and count(*)>0" replace: - pause: short - x: "*" - x: "translate(name(.), '-_', ' ')" - name: infix-intent # uncaught intent -- speak as foo of arg1 comma arg2 .... tag: "*" match: "contains(@data-intent-property, ':infix:') and count(*)>0" replace: - pause: short - insert: nodes: "*" replace: [x: "translate(name(.), '-_', ' ')", pause: auto] - pause: short - name: function-intent # uncaught intent -- speak as foo of arg1 comma arg2 .... tag: "*" match: count(*)>0 replace: - x: "translate(name(.), '-_', ' ')" - T: ' ' - pause: short - insert: nodes: "*" replace: [{T: 'koma'}, {pause: auto}] - name: default-text # unknown leaf -- just speak the text -- could be a literal intent tag: "*" match: "." replace: - x: "translate(name(), '-', ' ')"