Notation.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*************************************************************
  2. *
  3. * Copyright (c) 2018-2022 The MathJax Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @fileoverview Implements utilities for notations for menclose elements
  19. *
  20. * @author dpvc@mathjax.org (Davide Cervone)
  21. */
  22. import {CHTMLmenclose} from './Wrappers/menclose.js';
  23. import * as Notation from '../common/Notation.js';
  24. export * from '../common/Notation.js';
  25. /*
  26. * Shorthands for common types
  27. */
  28. export type RENDERER<N, T, D> = Notation.Renderer<CHTMLmenclose<N, T, D>, N>;
  29. export type DEFPAIR<N, T, D> = Notation.DefPair<CHTMLmenclose<N, T, D>, N>;
  30. /**
  31. * Create a named element (handled by CSS), and adjust it if thickness is non-standard
  32. *
  33. * @param {string} name The name of the element to create
  34. * @param {string} offset The offset direction to adjust if thickness is non-standard
  35. * @return {RENDERER} The renderer function for the given element name
  36. */
  37. export const RenderElement = function<N, T, D>(name: string, offset: string = ''): RENDERER<N, T, D> {
  38. return ((node, _child) => {
  39. const shape = node.adjustBorder(node.html('mjx-' + name));
  40. if (offset) {
  41. const d = node.getOffset(offset);
  42. if (node.thickness !== Notation.THICKNESS || d) {
  43. const transform = `translate${offset}(${node.em(node.thickness / 2 - d)})`;
  44. node.adaptor.setStyle(shape, 'transform', transform);
  45. }
  46. }
  47. node.adaptor.append(node.chtml, shape);
  48. }) as Notation.Renderer<CHTMLmenclose<N, T, D>, N>;
  49. };
  50. /**
  51. * @param {Notation.Side} side The side on which a border should appear
  52. * @return {DEFPAIR} The notation definition for the notation having a line on the given side
  53. */
  54. export const Border = function<N, T, D>(side: Notation.Side): DEFPAIR<N, T, D> {
  55. return Notation.CommonBorder<CHTMLmenclose<N, T, D>, N>((node, child) => {
  56. node.adaptor.setStyle(child, 'border-' + side, node.em(node.thickness) + ' solid');
  57. })(side);
  58. };
  59. /**
  60. * @param {string} name The name of the notation to define
  61. * @param {Notation.Side} side1 The first side to get a border
  62. * @param {Notation.Side} side2 The second side to get a border
  63. * @return {DEFPAIR} The notation definition for the notation having lines on two sides
  64. */
  65. export const Border2 = function<N, T, D>(name: string, side1: Notation.Side, side2: Notation.Side): DEFPAIR<N, T, D> {
  66. return Notation.CommonBorder2<CHTMLmenclose<N, T, D>, N>((node, child) => {
  67. const border = node.em(node.thickness) + ' solid';
  68. node.adaptor.setStyle(child, 'border-' + side1, border);
  69. node.adaptor.setStyle(child, 'border-' + side2, border);
  70. })(name, side1, side2);
  71. };
  72. /**
  73. * @param {string} name The name of the diagonal strike to define
  74. * @param {number} neg 1 or -1 to use with the angle
  75. * @return {DEFPAIR} The notation definition for the diagonal strike
  76. */
  77. export const DiagonalStrike = function<N, T, D>(name: string, neg: number): DEFPAIR<N, T, D> {
  78. return Notation.CommonDiagonalStrike<CHTMLmenclose<N, T, D>, N>((cname: string) => (node, _child) => {
  79. const {w, h, d} = node.getBBox();
  80. const [a, W] = node.getArgMod(w, h + d);
  81. const t = neg * node.thickness / 2;
  82. const strike = node.adjustBorder(node.html(cname, {style: {
  83. width: node.em(W),
  84. transform: 'rotate(' + node.fixed(-neg * a) + 'rad) translateY(' + t + 'em)',
  85. }}));
  86. node.adaptor.append(node.chtml, strike);
  87. })(name);
  88. };
  89. /**
  90. * @param {string} name The name of the diagonal arrow to define
  91. * @return {DEFPAIR} The notation definition for the diagonal arrow
  92. */
  93. export const DiagonalArrow = function<N, T, D>(name: string): DEFPAIR<N, T, D> {
  94. return Notation.CommonDiagonalArrow<CHTMLmenclose<N, T, D>, N>((node, arrow) => {
  95. node.adaptor.append(node.chtml, arrow);
  96. })(name);
  97. };
  98. /**
  99. * @param {string} name The name of the horizontal or vertical arrow to define
  100. * @return {DEFPAIR} The notation definition for the arrow
  101. */
  102. export const Arrow = function<N, T, D>(name: string): DEFPAIR<N, T, D> {
  103. return Notation.CommonArrow<CHTMLmenclose<N, T, D>, N>((node, arrow) => {
  104. node.adaptor.append(node.chtml, arrow);
  105. })(name);
  106. };