braille_store.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { MathStore } from './math_store.js';
  2. import { activate } from '../semantic_tree/semantic_annotations.js';
  3. import { SemanticMap } from '../semantic_tree/semantic_attr.js';
  4. import { SemanticType, SemanticRole } from '../semantic_tree/semantic_meaning.js';
  5. export class BrailleStore extends MathStore {
  6. constructor() {
  7. super(...arguments);
  8. this.modality = 'braille';
  9. this.customTranscriptions = {
  10. '\u22ca': '⠈⠡⠳'
  11. };
  12. }
  13. evaluateString(str) {
  14. const descs = [];
  15. const text = Array.from(str);
  16. for (let i = 0; i < text.length; i++) {
  17. descs.push(this.evaluateCharacter(text[i]));
  18. }
  19. return descs;
  20. }
  21. annotations() {
  22. for (let i = 0, annotator; (annotator = this.annotators[i]); i++) {
  23. activate(this.locale, annotator);
  24. }
  25. }
  26. }
  27. export class EuroStore extends BrailleStore {
  28. constructor() {
  29. super(...arguments);
  30. this.locale = 'euro';
  31. this.customTranscriptions = {};
  32. this.customCommands = {
  33. '\\cdot': '*',
  34. '\\lt': '<',
  35. '\\gt': '>'
  36. };
  37. this.lastSpecial = false;
  38. this.specialChars = ['^', '_', '{', '}'];
  39. }
  40. evaluateString(str) {
  41. const regexp = /(\\[a-z]+|\\{|\\}|\\\\)/i;
  42. const split = str.split(regexp);
  43. const cleaned = this.cleanup(split);
  44. return super.evaluateString(cleaned);
  45. }
  46. cleanup(commands) {
  47. const cleaned = [];
  48. let intext = false;
  49. let lastcom = null;
  50. for (let command of commands) {
  51. if (command.match(/^\\/)) {
  52. if (command === '\\text') {
  53. intext = true;
  54. }
  55. if (this.addSpace(SemanticMap.LatexCommands.get(command))) {
  56. cleaned.push(' ');
  57. }
  58. command = this.customCommands[command] || command;
  59. const newcom = command.match(/^\\/);
  60. if (newcom && command.match(/^\\[a-zA-Z]+$/) && lastcom) {
  61. cleaned.push(' ');
  62. }
  63. lastcom = newcom ? command : null;
  64. cleaned.push(command);
  65. continue;
  66. }
  67. const rest = command.split('');
  68. for (const char of rest) {
  69. if (intext) {
  70. cleaned.push(char);
  71. intext = char !== '}';
  72. lastcom = null;
  73. continue;
  74. }
  75. if (char.match(/[a-z]/i) && lastcom) {
  76. lastcom = null;
  77. cleaned.push(' ');
  78. cleaned.push(char);
  79. continue;
  80. }
  81. if (char.match(/\s/))
  82. continue;
  83. if (this.addSpace(char)) {
  84. cleaned.push(' ');
  85. }
  86. cleaned.push(char);
  87. lastcom = null;
  88. }
  89. }
  90. return cleaned.join('');
  91. }
  92. addSpace(char) {
  93. if (!char)
  94. return false;
  95. if (this.specialChars.indexOf(char) !== -1) {
  96. this.lastSpecial = true;
  97. return false;
  98. }
  99. if (this.lastSpecial) {
  100. this.lastSpecial = false;
  101. return false;
  102. }
  103. const meaning = SemanticMap.Meaning.get(char);
  104. return (meaning.type === SemanticType.OPERATOR ||
  105. meaning.type === SemanticType.RELATION ||
  106. (meaning.type === SemanticType.PUNCTUATION &&
  107. meaning.role === SemanticRole.COLON));
  108. }
  109. }