temml 0.10.16 → 0.10.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  | Library | Minified JavaScript + CSS |
4
4
  |:--------------|:-------------------------:|
5
- | Temml | 146 KB |
5
+ | Temml | 150 KB |
6
6
  | MathJax 2.7.5 | 338 KB |
7
7
  | KaTeX | 280 KB |
8
8
  | TeXZilla | 168 KB |
9
9
 
10
- As a futher advantage, Temml can use local system fonts. The minimum Temml installation serves a font file that is only 12kb. Sadly, Chromium has some rendering bugs when using system fonts. It
10
+ As a futher advantage, Temml can use local system fonts. The minimum Temml installation serves a font file that is only 10kb. Sadly, Chromium has some rendering bugs when using system fonts. It
11
11
  work better with the Latin Modern font, a 380 KB file.
12
12
 
13
13
  Temml’s coverage of LaTeX functions is as good as MathJax, slightly better than KaTeX 0.16.0 and substantially better than TeXZilla. See a [detailed coverage comparison](https://temml.org/docs/en/comparison.html).
@@ -0,0 +1,42 @@
1
+ # Copy-tex extension
2
+
3
+ This extension modifies the copy/paste behavior in any browser supporting the
4
+ [Clipboard API][1] so that, when a user selects and copies `<math>` elements, the
5
+ text content of the resulting clipboard replaces `<math>` elements with their LaTeX
6
+ source surrounded by specified delimiters.
7
+
8
+ The default delimiters are `$…$` for inline math and `$$…$$` for display math,
9
+ but you can switch them to e.g. `\(…\)` and `\[…\]` by modifying
10
+ `copyDelimiters` in [the source code][2]. Note that a selection containing part
11
+ of a math element gets extended to include the entire element.
12
+
13
+ `<math>` elements must include an `<annotation>` element containing the LaTeX source,
14
+ so when you run Temml, be sure to include `annotate: "true"` in the Temml rendering
15
+ options.
16
+
17
+ Note that soft line breaks cannot co-exist with an `<annotation>` element. You’ll have
18
+ to choose one or the other.
19
+
20
+ ## Usage
21
+
22
+ This extension isn't part of Temml proper, so the script needs to be included
23
+ (via a `<script>` tag) in the page along with Temml itself. For example:
24
+
25
+ ```
26
+ <head>
27
+
28
+ <link rel="stylesheet" href="./Temml-Local.css">
29
+ <script src="./temml.min.js"></script>
30
+ <script src="./copy-tex.min.js"></script>
31
+
32
+ </head>
33
+ ```
34
+
35
+ See [copy-tex.html][3] for an example.
36
+
37
+
38
+ [1]: https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent
39
+
40
+ [2]: https://github.com/ronkok/Temml/tree/main/contrib/copy-tex/copy-tex.js
41
+
42
+ [3]: https://temml.org/copy-tex.html
@@ -0,0 +1,66 @@
1
+ // Mostly, a copy of Eric Demaine's copy-tex extension for KaTex
2
+
3
+ // Return <math> element, or null if not found.
4
+ function closestMath(node) {
5
+ // If node is a Text Node, for example, go up to containing Element,
6
+ // where we can apply the `closest` method.
7
+ const element = (node instanceof Element ? node : node.parentElement)
8
+ return element && element.closest('math')
9
+ }
10
+
11
+ const defaultCopyDelimiters = {
12
+ inline: ['$', '$'], // alternative: ['\(', '\)']
13
+ display: ['$$', '$$'] // alternative: ['\[', '\]']
14
+ };
15
+
16
+ // Replace math elements with their TeX source, given an <annotation> element.
17
+ function replaceMathwithTeX(fragment, copyDelimiters = defaultCopyDelimiters) {
18
+ const mathElements = fragment.querySelectorAll('math');
19
+ for (let i = 0; i < mathElements.length; i++) {
20
+ const element = mathElements[i];
21
+ const texSource = element.querySelector('annotation');
22
+ if (texSource) {
23
+ if (element.replaceWith) { element.replaceWith(texSource) }
24
+ texSource.innerHTML = copyDelimiters.inline[0] +
25
+ texSource.innerHTML + copyDelimiters.inline[1];
26
+ }
27
+ }
28
+ return fragment
29
+ }
30
+
31
+ // Global copy handler to modify behavior on/within math elements.
32
+ document.addEventListener('copy', function(event) {
33
+ const selection = window.getSelection()
34
+ if (selection.isCollapsed || !event.clipboardData) {
35
+ return // default action OK if selection is empty or unchangeable
36
+ }
37
+ const clipboardData = event.clipboardData
38
+ const range = selection.getRangeAt(0)
39
+
40
+ // When start point is within a formula, expand to entire formula.
41
+ const startMath = closestMath(range.startContainer);
42
+ if (startMath) {
43
+ range.setStartBefore(startMath)
44
+ }
45
+
46
+ // Similarly, when end point is within a formula, expand to entire formula.
47
+ const endMath = closestMath(range.endContainer);
48
+ if (endMath) {
49
+ range.setEndAfter(endMath)
50
+ }
51
+
52
+ const fragment = range.cloneContents()
53
+ if (!fragment.querySelector('annotation')) {
54
+ return // default action OK if no annotation elements
55
+ }
56
+
57
+ const htmlContents = Array.prototype.map.call(fragment.childNodes,
58
+ (el) => (el instanceof Text ? el.textContent : el.outerHTML)).join('')
59
+
60
+ // Preserve usual HTML copy/paste behavior.
61
+ clipboardData.setData('text/html', htmlContents)
62
+ // Rewrite plain-text version.
63
+ clipboardData.setData('text/plain', replaceMathwithTeX(fragment).textContent)
64
+ // Prevent normal copy handling.
65
+ event.preventDefault()
66
+ })
@@ -0,0 +1 @@
1
+ function closestMath(t){const e=t instanceof Element?t:t.parentElement;return e&&e.closest("math")}const defaultCopyDelimiters={inline:["$","$"],display:["$$","$$"]};function replaceMathwithTeX(t,e=defaultCopyDelimiters){const n=t.querySelectorAll("math");for(let t=0;t<n.length;t++){const o=n[t],a=o.querySelector("annotation");a&&(o.replaceWith&&o.replaceWith(a),a.innerHTML=e.inline[0]+a.innerHTML+e.inline[1])}return t}document.addEventListener("copy",(function(t){const e=window.getSelection();if(e.isCollapsed||!t.clipboardData)return;const n=t.clipboardData,o=e.getRangeAt(0),a=closestMath(o.startContainer);a&&o.setStartBefore(a);const r=closestMath(o.endContainer);r&&o.setEndAfter(r);const i=o.cloneContents();if(!i.querySelector("annotation"))return;const l=Array.prototype.map.call(i.childNodes,(t=>t instanceof Text?t.textContent:t.outerHTML)).join("");n.setData("text/html",l),n.setData("text/plain",replaceMathwithTeX(i).textContent),t.preventDefault()}));
@@ -52,17 +52,37 @@ mo.prime-pad {
52
52
  padding-left: 0.08em;
53
53
  }
54
54
 
55
- /* Stretch \widetilde in Chromium */
55
+ /* Array cell justification in Firefox & WebKit */
56
+ .tml-right {
57
+ text-align: right;
58
+ }
59
+ .tml-left {
60
+ text-align: left;
61
+ }
62
+
63
+ /* Stretch \widetilde & set array cell justification in Chromium */
56
64
  @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
57
65
  .tml-crooked-2 {
58
66
  transform: scale(2.0, 1.1)
59
67
  }
60
68
  .tml-crooked-3 {
61
- transform: scale(3.0, 1.1)
69
+ transform: scale(3.0, 1.3)
62
70
  }
63
71
  .tml-crooked-4 {
64
- transform: scale(4.0, 1.1)
72
+ transform: scale(4.0, 1.4)
73
+ }
74
+ .tml-right {
75
+ text-align: -webkit-right;
65
76
  }
77
+ .tml-left {
78
+ text-align: -webkit-left;
79
+ }
80
+ }
81
+
82
+ /* Adjust WebKit accents */
83
+ @supports (-webkit-backdrop-filter: blur(1px)) {
84
+ .tml-xshift { transform: translate(0px, 0.45em) }
85
+ .tml-capshift { transform: translate(0px, 0.35em) }
66
86
  }
67
87
 
68
88
  /* flex-wrap for line-breaking in Chromium */
@@ -62,7 +62,15 @@ mo.prime-pad {
62
62
  padding-left: 0.08em;
63
63
  }
64
64
 
65
- /* Stretch \widetilde in Chromium */
65
+ /* Array cell justification in Firefox & WebKit */
66
+ .tml-right {
67
+ text-align: right;
68
+ }
69
+ .tml-left {
70
+ text-align: left;
71
+ }
72
+
73
+ /* Stretch \widetilde & set array cell justification in Chromium */
66
74
  @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
67
75
  .tml-crooked-2 {
68
76
  transform: scale(2.0, 1.1)
@@ -73,6 +81,18 @@ mo.prime-pad {
73
81
  .tml-crooked-4 {
74
82
  transform: scale(4.0, 1.4)
75
83
  }
84
+ .tml-right {
85
+ text-align: -webkit-right;
86
+ }
87
+ .tml-left {
88
+ text-align: -webkit-left;
89
+ }
90
+ }
91
+
92
+ /* Adjust WebKit accents */
93
+ @supports (-webkit-backdrop-filter: blur(1px)) {
94
+ .tml-xshift { transform: translate(0px, 0.45em) }
95
+ .tml-capshift { transform: translate(0px, 0.35em) }
76
96
  }
77
97
 
78
98
  /* flex-wrap for line-breaking in Chromium */
@@ -59,17 +59,37 @@ mo.prime-pad {
59
59
  padding-left: 0.08em;
60
60
  }
61
61
 
62
- /* Stretch \widetilde in Chromium */
62
+ /* Array cell justification in Firefox & WebKit */
63
+ .tml-right {
64
+ text-align: right;
65
+ }
66
+ .tml-left {
67
+ text-align: left;
68
+ }
69
+
70
+ /* Stretch \widetilde & set array cell justification in Chromium */
63
71
  @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
64
72
  .tml-crooked-2 {
65
73
  transform: scale(2.0, 1.1)
66
74
  }
67
75
  .tml-crooked-3 {
68
- transform: scale(3.0, 1.1)
76
+ transform: scale(3.0, 1.3)
69
77
  }
70
78
  .tml-crooked-4 {
71
- transform: scale(4.0, 1.2)
79
+ transform: scale(4.0, 1.4)
80
+ }
81
+ .tml-right {
82
+ text-align: -webkit-right;
72
83
  }
84
+ .tml-left {
85
+ text-align: -webkit-left;
86
+ }
87
+ }
88
+
89
+ /* Adjust WebKit accents */
90
+ @supports (-webkit-backdrop-filter: blur(1px)) {
91
+ .tml-xshift { transform: translate(0px, 0.45em) }
92
+ .tml-capshift { transform: translate(0px, 0.35em) }
73
93
  }
74
94
 
75
95
  /* flex-wrap for line-breaking in Chromium */
@@ -45,17 +45,37 @@ mo.prime-pad {
45
45
  padding-left: 0.08em;
46
46
  }
47
47
 
48
- /* Stretch \widetilde in Chromium */
48
+ /* Array cell justification in Firefox & WebKit */
49
+ .tml-right {
50
+ text-align: right;
51
+ }
52
+ .tml-left {
53
+ text-align: left;
54
+ }
55
+
56
+ /* Stretch \widetilde & set array cell justification in Chromium */
49
57
  @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
50
58
  .tml-crooked-2 {
51
59
  transform: scale(2.0, 1.1)
52
60
  }
53
61
  .tml-crooked-3 {
54
- transform: scale(3.0, 1.1)
62
+ transform: scale(3.0, 1.3)
55
63
  }
56
64
  .tml-crooked-4 {
57
- transform: scale(4.0, 1.1)
65
+ transform: scale(4.0, 1.4)
66
+ }
67
+ .tml-right {
68
+ text-align: -webkit-right;
58
69
  }
70
+ .tml-left {
71
+ text-align: -webkit-left;
72
+ }
73
+ }
74
+
75
+ /* Adjust WebKit accents */
76
+ @supports (-webkit-backdrop-filter: blur(1px)) {
77
+ .tml-xshift { transform: translate(0px, 0.45em) }
78
+ .tml-capshift { transform: translate(0px, 0.35em) }
59
79
  }
60
80
 
61
81
  /* flex-wrap for line-breaking in Chromium */
@@ -53,7 +53,15 @@ mo.prime-pad {
53
53
  padding-left: 0.08em;
54
54
  }
55
55
 
56
- /* Stretch \widetilde in Chromium */
56
+ /* Array cell justification in Firefox & WebKit */
57
+ .tml-right {
58
+ text-align: right;
59
+ }
60
+ .tml-left {
61
+ text-align: left;
62
+ }
63
+
64
+ /* Stretch \widetilde & set array cell justification in Chromium */
57
65
  @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
58
66
  .tml-crooked-2 {
59
67
  transform: scale(2.0, 1.1)
@@ -64,6 +72,18 @@ mo.prime-pad {
64
72
  .tml-crooked-4 {
65
73
  transform: scale(4.0, 1.4)
66
74
  }
75
+ .tml-right {
76
+ text-align: -webkit-right;
77
+ }
78
+ .tml-left {
79
+ text-align: -webkit-left;
80
+ }
81
+ }
82
+
83
+ /* Adjust WebKit accents */
84
+ @supports (-webkit-backdrop-filter: blur(1px)) {
85
+ .tml-xshift { transform: translate(0px, 0.45em) }
86
+ .tml-capshift { transform: translate(0px, 0.35em) }
67
87
  }
68
88
 
69
89
  /* flex-wrap for line-breaking in Chromium */